Commit e3a6d0e91989180ae0b849b6eafd18c98a0566c0
1 parent
b1483469
change the whole thing to be more edge triggered no matter wich poll method is u…
…sed. In fact this works now with edge triggered epoll
Showing
27 changed files
with
611 additions
and
500 deletions
include/tr/_comm_manager.h
0 → 100644
1 | +/** | |
2 | + * \file | |
3 | + * | |
4 | + * \author Georg Hopp | |
5 | + * | |
6 | + * \copyright | |
7 | + * Copyright © 2014 Georg Hopp | |
8 | + * | |
9 | + * This program is free software: you can redistribute it and/or modify | |
10 | + * it under the terms of the GNU General Public License as published by | |
11 | + * the Free Software Foundation, either version 3 of the License, or | |
12 | + * (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | + * GNU General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU General Public License | |
20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | + */ | |
22 | + | |
23 | +#ifndef __INT_TR_COMM_MANAGER_H__ | |
24 | +#define __INT_TR_COMM_MANAGER_H__ | |
25 | + | |
26 | +#include "tr/comm_end_point.h" | |
27 | +#include "tr/connect_entry_point.h" | |
28 | + | |
29 | +#define TR_ISSUE_IO_EVENT(this, type, subject) \ | |
30 | + TR_eventHandlerIssueEvent((TR_EventHandler)(this), TR_eventSubjectEmit( \ | |
31 | + (TR_EventSubject)(subject), type, NULL)) | |
32 | + | |
33 | +#define TR_ISSUE_IO_ACC_EVENT(this, subject) \ | |
34 | + (TR_ISSUE_IO_EVENT(this, TR_CET_EVENT_ACC_READY, subject)) | |
35 | +#define TR_ISSUE_IO_READ_EVENT(this, subject) \ | |
36 | + (TR_ISSUE_IO_EVENT(this, TR_CEP_EVENT_DO_READ, subject)) | |
37 | +#define TR_ISSUE_IO_WRITE_EVENT(this, subject) \ | |
38 | + (TR_ISSUE_IO_EVENT(this, TR_CEP_EVENT_DO_WRITE, subject)) | |
39 | +#define TR_ISSUE_IO_CLOSE_EVENT(this, subject) \ | |
40 | + (TR_ISSUE_IO_EVENT(this, TR_CEP_EVENT_CLOSE, subject)) | |
41 | +#define TR_ISSUE_IO_SHUT_READ_EVENT(this, subject) \ | |
42 | + (TR_ISSUE_IO_EVENT(this, TR_CEP_EVENT_SHUT_READ, subject)) | |
43 | +#define TR_ISSUE_IO_SHUT_WRITE_EVENT(this, subject) \ | |
44 | + (TR_ISSUE_IO_EVENT(this, TR_CEP_EVENT_SHUT_WRITE, subject)) | |
45 | + | |
46 | +#endif // __INT_TR_COMM_MANAGER_H__ | |
47 | + | |
48 | +// vim: set ts=4 sw=4: | |
49 | + | ... | ... |
... | ... | @@ -29,34 +29,40 @@ |
29 | 29 | #include "trevent.h" |
30 | 30 | #include "trdata.h" |
31 | 31 | |
32 | +/* | |
33 | + * Read ahead limits. | |
34 | + * These values should be conficurable in the future. | |
35 | + */ | |
36 | +#define CEP_WRITE_BUFFER_THRESHOLD 128 * 1024 | |
37 | + | |
32 | 38 | TR_CLASS(TR_CommEndPoint) { |
33 | 39 | TR_EXTENDS(TR_EventSubject); |
34 | 40 | |
35 | 41 | void * protocol; // will be type TR_Protocol as soon as it is there. |
36 | 42 | TR_Socket transport; |
37 | - size_t read_chunk_size; | |
38 | 43 | int do_close; |
39 | - TR_Queue read_buffer; | |
40 | 44 | TR_Queue write_buffer; |
45 | + size_t write_buffer_size; | |
46 | + size_t read_chunk_size; // bytes | |
41 | 47 | }; |
42 | 48 | TR_INSTANCE_INIT(TR_CommEndPoint); |
43 | 49 | TR_CLASSVARS_DECL(TR_CommEndPoint) { |
44 | 50 | TR_CV_EXTENDS(TR_EventSubject); |
45 | 51 | }; |
46 | 52 | |
47 | -#define TR_CEP_EVENT_READ_READY 0 | |
48 | -#define TR_CEP_EVENT_READ_BLOCK 1 | |
49 | -#define TR_CEP_EVENT_WRITE_READY 2 | |
50 | -#define TR_CEP_EVENT_UPGRADE 3 | |
51 | -#define TR_CEP_EVENT_NEW_DATA 4 | |
52 | -#define TR_CEP_EVENT_PENDING_DATA 5 | |
53 | -#define TR_CEP_EVENT_END_DATA 6 | |
54 | -#define TR_CEP_EVENT_NEW_MSG 7 | |
55 | -#define TR_CEP_EVENT_SEND_MSG 8 | |
56 | -#define TR_CEP_EVENT_SHUT_READ 9 | |
57 | -#define TR_CEP_EVENT_SHUT_WRITE 10 | |
58 | -#define TR_CEP_EVENT_CLOSE 11 | |
59 | -#define TR_CEP_EVENT_MAX ((size_t)TR_CEP_EVENT_CLOSE) | |
53 | +#define TR_CEP_EVENT_DO_READ 0 // IoHandler | |
54 | +#define TR_CEP_EVENT_DO_WRITE 1 // IoHandler | |
55 | +#define TR_CEP_EVENT_READ_BLOCK 2 // CommManager | |
56 | +#define TR_CEP_EVENT_WRITE_BLOCK 3 // CommManager | |
57 | +#define TR_CEP_EVENT_NEW_DATA 4 // ProtocolHandler | |
58 | +#define TR_CEP_EVENT_NEW_MSG 5 // Application | |
59 | +#define TR_CEP_EVENT_MSG_READY 6 // ProtocolHandler | |
60 | +#define TR_CEP_EVENT_DATA_READY 7 // CommManager | |
61 | +#define TR_CEP_EVENT_DATA_END 8 // CommManager | |
62 | +#define TR_CEP_EVENT_SHUT_READ 9 // CommManager | |
63 | +#define TR_CEP_EVENT_SHUT_WRITE 10 // CommManager | |
64 | +#define TR_CEP_EVENT_CLOSE 11 // CommManager | |
65 | +#define TR_CEP_EVENT_MAX ((size_t)TR_CEP_EVENT_CLOSE) | |
60 | 66 | |
61 | 67 | #define TR_cepSetClose(ep) ((ep)->do_close = 1) |
62 | 68 | #define TR_cepHasProto(ep, proto) (TR_INSTANCE_OF(proto, TR_cepGetProto(ep))) |
... | ... | @@ -67,8 +73,8 @@ TR_CLASSVARS_DECL(TR_CommEndPoint) { |
67 | 73 | |
68 | 74 | void TR_cepAppendReadData(TR_CommEndPoint, TR_RemoteData); |
69 | 75 | void TR_cepAppendWriteData(TR_CommEndPoint, TR_RemoteData); |
70 | -int TR_cepBufferRead(TR_CommEndPoint); | |
71 | -int TR_cepWriteBuffered(TR_CommEndPoint); | |
76 | +int TR_commEndPointRead(TR_CommEndPoint, TR_RemoteData *); | |
77 | +int TR_cepWriteBuffered(TR_CommEndPoint, size_t *); | |
72 | 78 | |
73 | 79 | #endif // __TR_COMM_END_POINT_H__ |
74 | 80 | ... | ... |
... | ... | @@ -26,6 +26,7 @@ |
26 | 26 | #include <sys/types.h> |
27 | 27 | |
28 | 28 | #include "trbase.h" |
29 | +#include "trdata.h" | |
29 | 30 | #include "trevent.h" |
30 | 31 | |
31 | 32 | #include "tr/comm_end_point.h" |
... | ... | @@ -34,6 +35,9 @@ TR_CLASS(TR_CommManager) { |
34 | 35 | TR_EXTENDS(TR_EventHandler); |
35 | 36 | |
36 | 37 | TR_CommEndPoint * endpoints; |
38 | + TR_Hash accept; | |
39 | + TR_Hash write; | |
40 | + TR_Hash read; | |
37 | 41 | size_t n_endpoints; |
38 | 42 | size_t max_handle; |
39 | 43 | }; |
... | ... | @@ -42,8 +46,7 @@ TR_CLASSVARS_DECL(TR_CommManager) { |
42 | 46 | TR_CV_EXTENDS(TR_EventHandler); |
43 | 47 | }; |
44 | 48 | |
45 | -void TR_commManagerAddEndpoint(void *, TR_CommEndPoint); | |
46 | -TR_EventDone TR_commManagerShutdown(void * _this, TR_Event event); | |
49 | +TR_EventDone TR_commManagerShutdown(TR_CommManager, TR_Event event); | |
47 | 50 | |
48 | 51 | #endif // __TR_COMM_MANAGER_H__ |
49 | 52 | ... | ... |
... | ... | @@ -31,8 +31,8 @@ |
31 | 31 | #include "tr/comm_end_point.h" |
32 | 32 | #include "tr/proto_message.h" |
33 | 33 | |
34 | -typedef TR_ProtoMessage (* fptr_TR_cepNextMessage)(void *); | |
35 | -typedef int (* fptr_TR_cepCompose)(void *, TR_ProtoMessage); | |
34 | +typedef TR_ProtoMessage (* fptr_TR_cepNextMessage)(void *, TR_RemoteData *); | |
35 | +typedef size_t (* fptr_TR_cepCompose)(void *, TR_ProtoMessage); | |
36 | 36 | |
37 | 37 | TR_INTERFACE(TR_CommEndPoint) { |
38 | 38 | TR_IFID; |
... | ... | @@ -40,8 +40,8 @@ TR_INTERFACE(TR_CommEndPoint) { |
40 | 40 | fptr_TR_cepCompose compose; |
41 | 41 | }; |
42 | 42 | |
43 | -TR_ProtoMessage TR_cepNextMessage(void *); | |
44 | -int TR_cepCompose(void *, TR_ProtoMessage); | |
43 | +TR_ProtoMessage TR_cepNextMessage(void *, TR_RemoteData *); | |
44 | +size_t TR_cepCompose(void *, TR_ProtoMessage); | |
45 | 45 | |
46 | 46 | #endif // __TR_INTERFACE_COMM_END_POINT_H__ |
47 | 47 | ... | ... |
... | ... | @@ -32,23 +32,17 @@ |
32 | 32 | |
33 | 33 | typedef TR_EventDone (* fptr_TR_commManagerAddEndpoint)(void *, TR_CommEndPoint); |
34 | 34 | typedef TR_EventDone (* fptr_TR_commManagerSelect)(void *, TR_Event, int); |
35 | -typedef TR_EventDone (* fptr_TR_commManagerEnableWrite)(void *, TR_Event); | |
36 | -typedef TR_EventDone (* fptr_TR_commManagerDisableWrite)(void *, TR_Event); | |
37 | -typedef TR_EventDone (* fptr_TR_commManagerEnableRead)(void *, TR_Event); | |
35 | +typedef TR_EventDone (* fptr_TR_commManagerPollWrite)(void *, TR_Event); | |
36 | +typedef TR_EventDone (* fptr_TR_commManagerPollRead)(void *, TR_Event); | |
38 | 37 | typedef TR_EventDone (* fptr_TR_commManagerClose)(void *, TR_Event); |
39 | -typedef TR_EventDone (* fptr_TR_commManagerShutdownRead)(void *, TR_Event); | |
40 | -typedef TR_EventDone (* fptr_TR_commManagerShutdownWrite)(void *, TR_Event); | |
41 | 38 | |
42 | 39 | TR_INTERFACE(TR_CommManager) { |
43 | 40 | TR_IFID; |
44 | - fptr_TR_commManagerAddEndpoint addEndpoint; | |
45 | - fptr_TR_commManagerSelect select; | |
46 | - fptr_TR_commManagerEnableWrite enableWrite; | |
47 | - fptr_TR_commManagerDisableWrite disableWrite; | |
48 | - fptr_TR_commManagerEnableRead enableRead; | |
49 | - fptr_TR_commManagerClose close; | |
50 | - fptr_TR_commManagerShutdownWrite shutdownWrite; | |
51 | - fptr_TR_commManagerShutdownRead shutdownRead; | |
41 | + fptr_TR_commManagerAddEndpoint addEndpoint; | |
42 | + fptr_TR_commManagerSelect select; | |
43 | + fptr_TR_commManagerPollWrite pollWrite; | |
44 | + fptr_TR_commManagerPollRead pollRead; | |
45 | + fptr_TR_commManagerClose close; | |
52 | 46 | }; |
53 | 47 | |
54 | 48 | void TR_commManagerAddEndpoint(void *, TR_CommEndPoint); | ... | ... |
... | ... | @@ -3,21 +3,21 @@ AUTOMAKE_OPTIONS = subdir-objects |
3 | 3 | |
4 | 4 | AM_CFLAGS += -I../include/ |
5 | 5 | |
6 | -TRCOMM = cep_append_read_data.c \ | |
7 | - cep_append_write_data.c \ | |
8 | - cet_accept.c \ | |
9 | - cep_buffer_read.c \ | |
6 | +TRCOMM = cet_accept.c \ | |
10 | 7 | cep_write_buffered.c \ |
8 | + comm_end_point_read.c \ | |
11 | 9 | comm_end_point.c \ |
12 | - comm_manager.c \ | |
13 | - comm_manager_poll.c \ | |
14 | - comm_manager_epoll.c \ | |
15 | - comm_manager_shutdown.c \ | |
16 | 10 | conn_entry_point.c \ |
17 | 11 | connection.c \ |
18 | 12 | connector.c \ |
19 | 13 | datagram_service.c \ |
20 | 14 | datagram_entry_point.c \ |
15 | + comm_manager.c \ | |
16 | + comm_manager_poll.c \ | |
17 | + comm_manager_epoll.c \ | |
18 | + comm_manager_shutdown.c \ | |
19 | + comm_manager_shutdown_read.c \ | |
20 | + comm_manager_shutdown_write.c \ | |
21 | 21 | io_handler.c \ |
22 | 22 | proto_message.c \ |
23 | 23 | protocol.c \ | ... | ... |
... | ... | @@ -26,24 +26,57 @@ |
26 | 26 | #include "tr/comm_end_point.h" |
27 | 27 | |
28 | 28 | int |
29 | -TR_cepWriteBuffered(TR_CommEndPoint this) | |
29 | +TR_cepWriteBuffered(TR_CommEndPoint this, size_t * size) | |
30 | 30 | { |
31 | 31 | TR_RemoteData data; |
32 | 32 | int send; |
33 | 33 | |
34 | + *size = 0; | |
35 | + | |
34 | 36 | data = TR_cepNextWriteData(this); |
35 | - send = TR_socketSend(this->transport, data); | |
36 | - | |
37 | - switch (send) { | |
38 | - case FALSE: // EAGAIN | |
39 | - TR_queuePutFirst(this->write_buffer, data); | |
40 | - break; | |
41 | - | |
42 | - case -1: // FAILURE | |
43 | - case -2: // remote close | |
44 | - default: | |
45 | - TR_delete(data); | |
46 | - break; | |
37 | + | |
38 | + while(data) { | |
39 | + send = TR_socketSend(this->transport, data); | |
40 | + | |
41 | + switch (send) { | |
42 | + case FALSE: // EAGAIN | |
43 | + case -3: // remote not ready | |
44 | + TR_queuePutFirst(this->write_buffer, data); | |
45 | + break; | |
46 | + | |
47 | + case -1: // FAILURE | |
48 | + case -2: // remote close | |
49 | + TR_delete(data); | |
50 | + TR_queueDestroy(this->write_buffer); | |
51 | + *size = this->write_buffer_size; | |
52 | + break; | |
53 | + | |
54 | + default: | |
55 | + { | |
56 | + TR_RemoteData new_data = NULL; | |
57 | + | |
58 | + if (send != ((TR_SizedData)data)->size) { | |
59 | + new_data = TR_new( | |
60 | + TR_RemoteData, | |
61 | + ((TR_SizedData)data)->data + send, | |
62 | + ((TR_SizedData)data)->size - send, | |
63 | + data->remote); | |
64 | + } else { | |
65 | + new_data = TR_cepNextWriteData(this); | |
66 | + } | |
67 | + | |
68 | + *size += send; | |
69 | + TR_delete(data); | |
70 | + data = new_data; | |
71 | + } | |
72 | + break; | |
73 | + } | |
74 | + | |
75 | + if (send <= 0) break; | |
76 | + } | |
77 | + | |
78 | + if (! data) { | |
79 | + return -4; // no more data to send | |
47 | 80 | } |
48 | 81 | |
49 | 82 | return send; | ... | ... |
... | ... | @@ -42,7 +42,6 @@ commEndPointCtor(void * _this, va_list * params) |
42 | 42 | this->protocol = va_arg(*params, TR_Protocol); |
43 | 43 | this->read_chunk_size = va_arg(*params, int); |
44 | 44 | this->do_close = 0; |
45 | - this->read_buffer = TR_new(TR_Queue); | |
46 | 45 | this->write_buffer = TR_new(TR_Queue); |
47 | 46 | |
48 | 47 | return 0; |
... | ... | @@ -55,52 +54,80 @@ commEndPointDtor(void * _this) |
55 | 54 | TR_CommEndPoint this = _this; |
56 | 55 | |
57 | 56 | TR_delete(this->transport); |
58 | - TR_delete(this->read_buffer); | |
59 | 57 | TR_delete(this->write_buffer); |
60 | 58 | } |
61 | 59 | |
62 | 60 | static |
61 | +unsigned long | |
62 | +commEndPointGetHash(void * _this) | |
63 | +{ | |
64 | + return (unsigned long)((TR_CommEndPoint)_this)->transport->handle; | |
65 | +} | |
66 | + | |
67 | +static | |
68 | +void | |
69 | +commEndPointHandleDouble(void * _current, void * _new) | |
70 | +{ | |
71 | + TR_CommEndPoint current = _current; | |
72 | + TR_CommEndPoint new = _new; | |
73 | + | |
74 | + // add will delete _new after this function is processed, so it's | |
75 | + // neccessary to cleanup _current and reinit it with whatever was | |
76 | + // in _new. | |
77 | + // This will only be called if _current and _new are different. | |
78 | + commEndPointDtor(current); | |
79 | + | |
80 | + current->transport = new->transport; | |
81 | + current->protocol = new->protocol; | |
82 | + current->read_chunk_size = new->read_chunk_size; | |
83 | + current->do_close = new->do_close; | |
84 | + current->write_buffer = new->write_buffer; | |
85 | +} | |
86 | + | |
87 | +static | |
63 | 88 | void |
64 | 89 | commEndPointCvInit(TR_class_ptr cls) |
65 | 90 | { |
66 | - TR_EVENT_CREATE(cls, TR_CEP_EVENT_READ_READY); | |
91 | + TR_EVENT_CREATE(cls, TR_CEP_EVENT_DO_READ); | |
92 | + TR_EVENT_CREATE(cls, TR_CEP_EVENT_DO_WRITE); | |
67 | 93 | TR_EVENT_CREATE(cls, TR_CEP_EVENT_READ_BLOCK); |
68 | - TR_EVENT_CREATE(cls, TR_CEP_EVENT_WRITE_READY); | |
69 | - TR_EVENT_CREATE(cls, TR_CEP_EVENT_UPGRADE); | |
94 | + TR_EVENT_CREATE(cls, TR_CEP_EVENT_WRITE_BLOCK); | |
70 | 95 | TR_EVENT_CREATE(cls, TR_CEP_EVENT_NEW_DATA); |
71 | - TR_EVENT_CREATE(cls, TR_CEP_EVENT_PENDING_DATA); | |
72 | - TR_EVENT_CREATE(cls, TR_CEP_EVENT_END_DATA); | |
73 | 96 | TR_EVENT_CREATE(cls, TR_CEP_EVENT_NEW_MSG); |
74 | - TR_EVENT_CREATE(cls, TR_CEP_EVENT_SEND_MSG); | |
97 | + TR_EVENT_CREATE(cls, TR_CEP_EVENT_MSG_READY); | |
98 | + TR_EVENT_CREATE(cls, TR_CEP_EVENT_DATA_READY); | |
99 | + TR_EVENT_CREATE(cls, TR_CEP_EVENT_DATA_END); | |
75 | 100 | TR_EVENT_CREATE(cls, TR_CEP_EVENT_SHUT_READ); |
76 | 101 | TR_EVENT_CREATE(cls, TR_CEP_EVENT_SHUT_WRITE); |
77 | 102 | TR_EVENT_CREATE(cls, TR_CEP_EVENT_CLOSE); |
78 | 103 | } |
79 | 104 | |
80 | 105 | const char * TR_cepEventStrings[] = { |
81 | - "TR_CEP_EVENT_READ_READY", | |
106 | + "TR_CEP_EVENT_DO_READ", | |
107 | + "TR_CEP_EVENT_DO_WRITE", | |
82 | 108 | "TR_CEP_EVENT_READ_BLOCK", |
83 | - "TR_CEP_EVENT_WRITE_READY", | |
84 | - "TR_CEP_EVENT_UPGRADE", | |
109 | + "TR_CEP_EVENT_WRITE_BLOCK", | |
85 | 110 | "TR_CEP_EVENT_NEW_DATA", |
86 | - "TR_CEP_EVENT_PENDING_DATA", | |
87 | - "TR_CEP_EVENT_END_DATA", | |
88 | 111 | "TR_CEP_EVENT_NEW_MSG", |
89 | - "TR_CEP_EVENT_SEND_MSG", | |
112 | + "TR_CEP_EVENT_MSG_READY", | |
113 | + "TR_CEP_EVENT_DATA_READY", | |
114 | + "TR_CEP_EVENT_DATA_END", | |
90 | 115 | "TR_CEP_EVENT_SHUT_READ", |
91 | 116 | "TR_CEP_EVENT_SHUT_WRITE", |
92 | - "TR_CEP_EVENT_CLOSE" | |
117 | + "TR_CEP_EVENT_CLOSE", | |
93 | 118 | }; |
94 | 119 | |
95 | 120 | intptr_t comm_end_point_events[TR_CEP_EVENT_MAX + 1]; |
96 | 121 | TR_INIT_IFACE(TR_Class, commEndPointCtor, commEndPointDtor, NULL); |
97 | 122 | TR_INIT_IFACE(TR_CommEndPoint, NULL, NULL); |
123 | +TR_INIT_IFACE(TR_Hashable, commEndPointGetHash, commEndPointHandleDouble); | |
98 | 124 | TR_CREATE_CLASS( |
99 | 125 | TR_CommEndPoint, |
100 | 126 | TR_EventSubject, |
101 | 127 | commEndPointCvInit, |
102 | 128 | TR_IF(TR_Class), |
103 | - TR_IF(TR_CommEndPoint)) = { | |
129 | + TR_IF(TR_CommEndPoint), | |
130 | + TR_IF(TR_Hashable)) = { | |
104 | 131 | { |
105 | 132 | TR_cepEventStrings, |
106 | 133 | TR_CEP_EVENT_MAX + 1, | ... | ... |
... | ... | @@ -25,10 +25,16 @@ |
25 | 25 | |
26 | 26 | #include "tr/comm_end_point.h" |
27 | 27 | |
28 | -void | |
29 | -TR_cepAppendReadData(TR_CommEndPoint this, TR_RemoteData data) | |
28 | +int | |
29 | +TR_commEndPointRead(TR_CommEndPoint this, TR_RemoteData * data_ptr) | |
30 | 30 | { |
31 | - TR_queuePut(this->read_buffer, data); | |
31 | + *data_ptr = TR_socketRecv(this->transport, this->read_chunk_size); | |
32 | + | |
33 | + if (! *data_ptr) return -1; // ment to trigger a close | |
34 | + if (*data_ptr == (void*)-1) return -2; // remote close... shutdown | |
35 | + if (*data_ptr == TR_emptyRemoteData) return FALSE; // read blocked | |
36 | + | |
37 | + return TRUE; | |
32 | 38 | } |
33 | 39 | |
34 | 40 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | #include <poll.h> |
25 | 25 | |
26 | 26 | #include "trbase.h" |
27 | +#include "trdata.h" | |
27 | 28 | #include "trevent.h" |
28 | 29 | |
29 | 30 | #include "tr/comm_end_point.h" |
... | ... | @@ -39,6 +40,9 @@ commManagerCtor(void * _this, va_list * params) |
39 | 40 | |
40 | 41 | TR_PARENTCALL(TR_CommManager, _this, TR_Class, ctor, params); |
41 | 42 | |
43 | + this->accept = TR_new(TR_Hash); | |
44 | + this->write = TR_new(TR_Hash); | |
45 | + this->read = TR_new(TR_Hash); | |
42 | 46 | this->n_endpoints = sysconf(_SC_OPEN_MAX); |
43 | 47 | this->endpoints = TR_calloc(sizeof(TR_CommEndPoint), this->n_endpoints); |
44 | 48 | |
... | ... | @@ -56,81 +60,98 @@ commManagerDtor(void * _this) |
56 | 60 | TR_delete(this->endpoints[i]); |
57 | 61 | } |
58 | 62 | TR_MEM_FREE(this->endpoints); |
63 | + TR_delete(this->read); | |
64 | + TR_delete(this->write); | |
65 | + TR_delete(this->accept); | |
59 | 66 | } |
60 | 67 | |
61 | 68 | static |
62 | 69 | TR_EventDone |
63 | -TR__commManagerAddEndpoint(void * _this, TR_Event event) | |
70 | +TR_commManagerEnableWrite(void * _this, TR_Event event) | |
64 | 71 | { |
65 | - TR_commManagerAddEndpoint( | |
66 | - (TR_CommManager)_this, | |
67 | - (TR_CommEndPoint)event->subject); | |
72 | + TR_CommManager this = _this; | |
73 | + | |
74 | + TR_hashAdd(this->write, event->subject); | |
75 | + | |
76 | + return TR_EVENT_DONE; | |
77 | +} | |
78 | + | |
79 | +static | |
80 | +TR_EventDone | |
81 | +TR_commManagerDisableWrite(void * _this, TR_Event event) | |
82 | +{ | |
83 | + TR_CommManager this = _this; | |
84 | + | |
85 | + TR_hashDeleteByVal(this->write, TR_hashableGetHash(event->subject)); | |
86 | + | |
87 | + return TR_EVENT_DONE; | |
88 | +} | |
89 | + | |
90 | +static | |
91 | +TR_EventDone | |
92 | +TR_commManagerAddEndpointEvt(TR_CommManager this, TR_Event event) | |
93 | +{ | |
94 | + TR_commManagerAddEndpoint(this, (TR_CommEndPoint)event->subject); | |
68 | 95 | |
69 | 96 | return TR_EVENT_DONE; |
70 | 97 | } |
71 | 98 | |
72 | 99 | TR_EventDone TR_commManagerSelect(void *, TR_Event, int); |
73 | -TR_EventDone TR_commManagerEnableWrite(void *, TR_Event); | |
74 | -TR_EventDone TR_commManagerDisableWrite(void *, TR_Event); | |
75 | -TR_EventDone TR_commManagerEnableRead(void *, TR_Event); | |
100 | +TR_EventDone TR_commManagerPollWrite(void *, TR_Event); | |
101 | +TR_EventDone TR_commManagerPollRead(void *, TR_Event); | |
76 | 102 | TR_EventDone TR_commManagerClose(void *, TR_Event); |
77 | -TR_EventDone TR_commManagerShutdownRead(void *, TR_Event); | |
78 | -TR_EventDone TR_commManagerShutdownWrite(void *, TR_Event); | |
103 | +TR_EventDone TR_commManagerShutdownRead(TR_CommManager, TR_Event); | |
104 | +TR_EventDone TR_commManagerShutdownWrite(TR_CommManager, TR_Event); | |
79 | 105 | |
80 | 106 | static |
81 | 107 | void |
82 | 108 | commManagerCvInit(TR_class_ptr cls) |
83 | 109 | { |
84 | 110 | TR_EVENT_HANDLER_SET_METHOD( |
85 | - cls, | |
86 | - TR_EventDispatcher, | |
111 | + cls, TR_EventDispatcher, | |
87 | 112 | TR_DISPATCHER_EVENT_DATA_WAIT, |
88 | 113 | TR_commManagerSelect); |
89 | 114 | TR_EVENT_HANDLER_SET_METHOD( |
90 | - cls, | |
91 | - TR_EventDispatcher, | |
115 | + cls, TR_EventDispatcher, | |
92 | 116 | TR_DISPATCHER_EVENT_SHUTDOWN, |
93 | 117 | TR_commManagerShutdown); |
94 | 118 | TR_EVENT_HANDLER_SET_METHOD( |
95 | - cls, | |
96 | - TR_Connection, | |
119 | + cls, TR_Connection, | |
97 | 120 | TR_CON_EVENT_NEW_CON, |
98 | - TR__commManagerAddEndpoint); | |
99 | - TR_EVENT_HANDLER_SET_METHOD( | |
100 | - cls, | |
101 | - TR_CommEndPoint, | |
102 | - TR_CEP_EVENT_PENDING_DATA, | |
103 | - TR_commManagerEnableWrite); | |
121 | + TR_commManagerAddEndpointEvt); | |
104 | 122 | TR_EVENT_HANDLER_SET_METHOD( |
105 | - cls, | |
106 | - TR_CommEndPoint, | |
107 | - TR_CEP_EVENT_END_DATA, | |
108 | - TR_commManagerDisableWrite); | |
123 | + cls, TR_CommEndPoint, | |
124 | + TR_CEP_EVENT_WRITE_BLOCK, | |
125 | + TR_commManagerPollWrite); | |
109 | 126 | TR_EVENT_HANDLER_SET_METHOD( |
110 | - cls, | |
111 | - TR_CommEndPoint, | |
127 | + cls, TR_CommEndPoint, | |
112 | 128 | TR_CEP_EVENT_READ_BLOCK, |
113 | - TR_commManagerEnableRead); | |
129 | + TR_commManagerPollRead); | |
114 | 130 | TR_EVENT_HANDLER_SET_METHOD( |
115 | - cls, | |
116 | - TR_CommEndPoint, | |
131 | + cls, TR_CommEndPoint, | |
117 | 132 | TR_CEP_EVENT_CLOSE, |
118 | 133 | TR_commManagerClose); |
119 | 134 | TR_EVENT_HANDLER_SET_METHOD( |
120 | - cls, | |
121 | - TR_CommEndPoint, | |
135 | + cls, TR_CommEndPoint, | |
122 | 136 | TR_CEP_EVENT_SHUT_READ, |
123 | 137 | TR_commManagerShutdownRead); |
124 | 138 | TR_EVENT_HANDLER_SET_METHOD( |
125 | - cls, | |
126 | - TR_CommEndPoint, | |
139 | + cls, TR_CommEndPoint, | |
127 | 140 | TR_CEP_EVENT_SHUT_WRITE, |
128 | 141 | TR_commManagerShutdownWrite); |
142 | + TR_EVENT_HANDLER_SET_METHOD( | |
143 | + cls, TR_CommEndPoint, | |
144 | + TR_CEP_EVENT_DATA_READY, | |
145 | + TR_commManagerEnableWrite); | |
146 | + TR_EVENT_HANDLER_SET_METHOD( | |
147 | + cls, TR_CommEndPoint, | |
148 | + TR_CEP_EVENT_DATA_END, | |
149 | + TR_commManagerDisableWrite); | |
129 | 150 | } |
130 | 151 | |
131 | 152 | TR_INSTANCE(TR_Hash, commManagerEventMethods); |
132 | 153 | TR_INIT_IFACE(TR_Class, commManagerCtor, commManagerDtor, NULL); |
133 | -TR_INIT_IFACE(TR_CommManager, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
154 | +TR_INIT_IFACE(TR_CommManager, NULL, NULL, NULL, NULL, NULL); | |
134 | 155 | TR_CREATE_CLASS( |
135 | 156 | TR_CommManager, |
136 | 157 | TR_EventHandler, | ... | ... |
... | ... | @@ -34,8 +34,9 @@ |
34 | 34 | #include "tr/comm_end_point.h" |
35 | 35 | #include "tr/connection.h" |
36 | 36 | #include "tr/connect_entry_point.h" |
37 | +#include "tr/_comm_manager.h" | |
37 | 38 | |
38 | -#define MAXEVENTS 256 | |
39 | +#define MAXEVENTS 1024 | |
39 | 40 | |
40 | 41 | struct epoll_event events[MAXEVENTS]; |
41 | 42 | |
... | ... | @@ -72,7 +73,7 @@ TR_commManagerEpollAddEndpoint(void * _this, TR_CommEndPoint endpoint) |
72 | 73 | int handle = endpoint->transport->handle; |
73 | 74 | struct epoll_event event; |
74 | 75 | |
75 | - this->events[handle] = EPOLLIN; | |
76 | + this->events[handle] = EPOLLET; | |
76 | 77 | event.data.ptr = endpoint; |
77 | 78 | event.events = this->events[handle]; |
78 | 79 | |
... | ... | @@ -84,69 +85,52 @@ void |
84 | 85 | TR_commManagerEpollSelect(void * _this, TR_Event event, int timeout) |
85 | 86 | { |
86 | 87 | TR_CommManagerEpoll this = _this; |
88 | + TR_CommManager cmgr = _this; | |
87 | 89 | int i, nevents; |
90 | + struct epoll_event _event; | |
88 | 91 | |
89 | 92 | nevents = epoll_wait(this->handle, events, MAXEVENTS, timeout); |
90 | 93 | |
91 | 94 | for (i=0; i<nevents; i++) { |
92 | 95 | TR_CommEndPoint endpoint = (TR_CommEndPoint)events[i].data.ptr; |
96 | + int handle = endpoint->transport->handle; | |
93 | 97 | |
94 | 98 | if ((events[i].events & EPOLLIN) == EPOLLIN) { |
95 | 99 | if (TR_INSTANCE_OF(TR_TcpSocket, endpoint->transport) |
96 | 100 | && ((TR_TcpSocket)endpoint->transport)->listen) { |
97 | - TR_eventHandlerIssueEvent((TR_EventHandler)this, | |
98 | - TR_eventSubjectEmit( | |
99 | - (TR_EventSubject)endpoint, | |
100 | - TR_CET_EVENT_ACC_READY, | |
101 | - NULL)); | |
101 | + TR_hashAdd(cmgr->accept, endpoint); | |
102 | 102 | } else { |
103 | - TR_eventHandlerIssueEvent((TR_EventHandler)this, | |
104 | - TR_eventSubjectEmit( | |
105 | - (TR_EventSubject)endpoint, | |
106 | - TR_CEP_EVENT_READ_READY, | |
107 | - NULL)); | |
103 | + TR_hashAdd(cmgr->read, endpoint); | |
104 | + | |
108 | 105 | } |
106 | + | |
107 | + this->events[handle] &= ~EPOLLIN; | |
108 | + _event.data.ptr = endpoint; | |
109 | + _event.events = this->events[handle]; | |
110 | + epoll_ctl(this->handle, EPOLL_CTL_MOD, handle, &_event); | |
109 | 111 | } |
110 | 112 | |
111 | 113 | if ((events[i].events & EPOLLOUT) == EPOLLOUT) { |
112 | - TR_eventHandlerIssueEvent((TR_EventHandler)this, | |
113 | - TR_eventSubjectEmit( | |
114 | - (TR_EventSubject)endpoint, | |
115 | - TR_CEP_EVENT_WRITE_READY, | |
116 | - NULL)); | |
114 | + TR_hashAdd(cmgr->write, endpoint); | |
115 | + this->events[handle] &= ~EPOLLOUT; | |
116 | + _event.data.ptr = endpoint; | |
117 | + _event.events = this->events[handle]; | |
118 | + epoll_ctl(this->handle, EPOLL_CTL_MOD, handle, &_event); | |
117 | 119 | } |
118 | 120 | } |
119 | 121 | } |
120 | 122 | |
121 | 123 | static |
124 | +inline | |
122 | 125 | void |
123 | -TR_commManagerEpollEnableWrite(void * _this, TR_Event event) | |
124 | -{ | |
125 | - TR_CommManagerEpoll this = _this; | |
126 | - TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; | |
127 | - | |
128 | - if (! TR_socketFinWr(endpoint->transport)) { | |
129 | - int handle = endpoint->transport->handle; | |
130 | - struct epoll_event _event; | |
131 | - | |
132 | - this->events[handle] |= EPOLLOUT; | |
133 | - _event.data.ptr = endpoint; | |
134 | - _event.events = this->events[handle]; | |
135 | - | |
136 | - epoll_ctl(this->handle, EPOLL_CTL_MOD, handle, &_event); | |
137 | - } | |
138 | -} | |
139 | - | |
140 | -static | |
141 | -void | |
142 | -TR_commManagerEpollDisableWrite(void * _this, TR_Event event) | |
126 | +TR_commManagerEpollEnable(void * _this, uint32_t mask, TR_Event event) | |
143 | 127 | { |
144 | 128 | TR_CommManagerEpoll this = _this; |
145 | 129 | TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
146 | 130 | int handle = endpoint->transport->handle; |
147 | 131 | struct epoll_event _event; |
148 | 132 | |
149 | - this->events[handle] &= ~EPOLLOUT; | |
133 | + this->events[handle] |= mask; | |
150 | 134 | _event.data.ptr = endpoint; |
151 | 135 | _event.events = this->events[handle]; |
152 | 136 | |
... | ... | @@ -155,37 +139,20 @@ TR_commManagerEpollDisableWrite(void * _this, TR_Event event) |
155 | 139 | |
156 | 140 | static |
157 | 141 | void |
158 | -TR_commManagerEpollEnableRead(void * _this, TR_Event event) | |
142 | +TR_commManagerEpollEnableWrite(void * _this, TR_Event event) | |
159 | 143 | { |
160 | - TR_CommManagerEpoll this = _this; | |
161 | - TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; | |
162 | - | |
163 | - if (! TR_socketFinRd(endpoint->transport)) { | |
164 | - int handle = endpoint->transport->handle; | |
165 | - struct epoll_event _event; | |
166 | - | |
167 | - this->events[handle] |= EPOLLIN; | |
168 | - _event.data.ptr = endpoint; | |
169 | - _event.events = this->events[handle]; | |
170 | - | |
171 | - epoll_ctl(this->handle, EPOLL_CTL_MOD, handle, &_event); | |
144 | + if (! TR_socketFinWr(((TR_CommEndPoint)event->subject)->transport)) { | |
145 | + TR_commManagerEpollEnable(_this, EPOLLOUT, event); | |
172 | 146 | } |
173 | 147 | } |
174 | 148 | |
175 | 149 | static |
176 | 150 | void |
177 | -TR_commManagerEpollDisableRead(void * _this, TR_Event event) | |
151 | +TR_commManagerEpollEnableRead(void * _this, TR_Event event) | |
178 | 152 | { |
179 | - TR_CommManagerEpoll this = _this; | |
180 | - TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; | |
181 | - int handle = endpoint->transport->handle; | |
182 | - struct epoll_event _event; | |
183 | - | |
184 | - this->events[handle] &= ~EPOLLIN; | |
185 | - _event.data.ptr = endpoint; | |
186 | - _event.events = this->events[handle]; | |
187 | - | |
188 | - epoll_ctl(this->handle, EPOLL_CTL_MOD, handle, &_event); | |
153 | + if (! TR_socketFinRd(((TR_CommEndPoint)event->subject)->transport)) { | |
154 | + TR_commManagerEpollEnable(_this, EPOLLIN, event); | |
155 | + } | |
189 | 156 | } |
190 | 157 | |
191 | 158 | static |
... | ... | @@ -207,14 +174,11 @@ TR_commManagerEpollCvInit(TR_class_ptr cls) { |
207 | 174 | TR_INIT_IFACE(TR_Class, commManagerEpollCtor, commManagerEpollDtor, NULL); |
208 | 175 | TR_INIT_IFACE( |
209 | 176 | TR_CommManager, |
210 | - TR_commManagerEpollAddEndpoint, // TR_CON_EVENT_NEW_CON | |
211 | - TR_commManagerEpollSelect, // TR_DISPATCHER_EVENT_DATA_WAIT | |
212 | - TR_commManagerEpollEnableWrite, // TR_CEP_EVENT_PENDING_DATA => WRITE_BLOCK | |
213 | - TR_commManagerEpollDisableWrite, // TR_CEP_EVENT_END_DATA | |
214 | - TR_commManagerEpollEnableRead, // TR_CEP_EVENT_READ_BLOCK | |
215 | - TR_commManagerEpollClose, // TR_CEP_EVENT_CLOSE | |
216 | - TR_commManagerEpollDisableWrite, // TR_CEP_EVENT_SHUT_READ | |
217 | - TR_commManagerEpollEnableRead); // TR_CEP_EVENT_SHUT_WRITE | |
177 | + TR_commManagerEpollAddEndpoint, | |
178 | + TR_commManagerEpollSelect, // TR_DISPATCHER_EVENT_DATA_WAIT | |
179 | + TR_commManagerEpollEnableWrite, // TR_CEP_EVENT_PENDING_DATA => WRITE_BLOCK | |
180 | + TR_commManagerEpollEnableRead, // TR_CEP_EVENT_READ_BLOCK | |
181 | + TR_commManagerEpollClose); // TR_CEP_EVENT_CLOSE | |
218 | 182 | TR_CREATE_CLASS( |
219 | 183 | TR_CommManagerEpoll, |
220 | 184 | TR_CommManager, | ... | ... |
... | ... | @@ -32,6 +32,7 @@ |
32 | 32 | #include "tr/comm_end_point.h" |
33 | 33 | #include "tr/connection.h" |
34 | 34 | #include "tr/connect_entry_point.h" |
35 | +#include "tr/_comm_manager.h" | |
35 | 36 | |
36 | 37 | static |
37 | 38 | int |
... | ... | @@ -69,9 +70,9 @@ TR_commManagerPollAddEndpoint(void * _this, TR_CommEndPoint endpoint) |
69 | 70 | TR_CommManagerPoll this = _this; |
70 | 71 | |
71 | 72 | this->fds[endpoint->transport->handle].fd = endpoint->transport->handle; |
72 | - this->fds[endpoint->transport->handle].events = POLLIN; | |
73 | + this->fds[endpoint->transport->handle].events = 0; | |
73 | 74 | } |
74 | - | |
75 | + | |
75 | 76 | static |
76 | 77 | void |
77 | 78 | TR_commManagerPollSelect(void * _this, TR_Event event, int timeout) |
... | ... | @@ -85,39 +86,28 @@ TR_commManagerPollSelect(void * _this, TR_Event event, int timeout) |
85 | 86 | |
86 | 87 | if (nevents) { |
87 | 88 | for (i = 0; i < cmgr->max_handle+1; i++) { |
88 | - TR_CommEndPoint endpoint = cmgr->endpoints[i]; | |
89 | - | |
90 | - if ((this->fds[i].revents & POLLIN) == POLLIN) { | |
91 | - TR_Event event; | |
89 | + if (this->fds[i].revents != 0) { | |
90 | + TR_CommEndPoint endpoint = cmgr->endpoints[i]; | |
92 | 91 | |
93 | 92 | nevents--; |
94 | - if (TR_INSTANCE_OF(TR_TcpSocket, endpoint->transport) | |
95 | - && ((TR_TcpSocket)endpoint->transport)->listen) { | |
96 | - event = TR_eventSubjectEmit( | |
97 | - (TR_EventSubject)endpoint, | |
98 | - TR_CET_EVENT_ACC_READY, | |
99 | - NULL); | |
100 | - } else { | |
101 | - event = TR_eventSubjectEmit( | |
102 | - (TR_EventSubject)endpoint, | |
103 | - TR_CEP_EVENT_READ_READY, | |
104 | - NULL); | |
105 | - } | |
106 | 93 | |
107 | - TR_eventHandlerIssueEvent((TR_EventHandler)this, event); | |
108 | - } | |
94 | + if ((this->fds[i].revents & POLLIN) == POLLIN) { | |
95 | + if (TR_INSTANCE_OF(TR_TcpSocket, endpoint->transport) | |
96 | + && ((TR_TcpSocket)endpoint->transport)->listen) { | |
97 | + TR_hashAdd(cmgr->accept, endpoint); | |
98 | + } else { | |
99 | + TR_hashAdd(cmgr->read, endpoint); | |
100 | + } | |
101 | + this->fds[endpoint->transport->handle].events &= ~POLLIN; | |
102 | + } | |
109 | 103 | |
110 | - if ((this->fds[i].revents & POLLOUT) == POLLOUT) { | |
111 | - nevents--; | |
112 | - TR_Event _event = TR_eventSubjectEmit( | |
113 | - (TR_EventSubject)endpoint, | |
114 | - TR_CEP_EVENT_WRITE_READY, | |
115 | - NULL); | |
104 | + if ((this->fds[i].revents & POLLOUT) == POLLOUT) { | |
105 | + TR_hashAdd(cmgr->write, endpoint); | |
106 | + this->fds[endpoint->transport->handle].events &= ~POLLOUT; | |
107 | + } | |
116 | 108 | |
117 | - TR_eventHandlerIssueEvent((TR_EventHandler)this, _event); | |
109 | + if (nevents <= 0) break; | |
118 | 110 | } |
119 | - | |
120 | - if (nevents <= 0) break; | |
121 | 111 | } |
122 | 112 | } |
123 | 113 | } |
... | ... | @@ -136,16 +126,6 @@ TR_commManagerPollEnableWrite(void * _this, TR_Event event) |
136 | 126 | |
137 | 127 | static |
138 | 128 | void |
139 | -TR_commManagerPollDisableWrite(void * _this, TR_Event event) | |
140 | -{ | |
141 | - TR_CommManagerPoll this = _this; | |
142 | - TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; | |
143 | - | |
144 | - this->fds[endpoint->transport->handle].events &= ~POLLOUT; | |
145 | -} | |
146 | - | |
147 | -static | |
148 | -void | |
149 | 129 | TR_commManagerPollEnableRead(void * _this, TR_Event event) |
150 | 130 | { |
151 | 131 | TR_CommManagerPoll this = _this; |
... | ... | @@ -158,16 +138,6 @@ TR_commManagerPollEnableRead(void * _this, TR_Event event) |
158 | 138 | |
159 | 139 | static |
160 | 140 | void |
161 | -TR_commManagerPollDisableRead(void * _this, TR_Event event) | |
162 | -{ | |
163 | - TR_CommManagerPoll this = _this; | |
164 | - TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; | |
165 | - | |
166 | - this->fds[endpoint->transport->handle].events &= ~POLLIN; | |
167 | -} | |
168 | - | |
169 | -static | |
170 | -void | |
171 | 141 | TR_commManagerPollClose(void * _this, TR_Event event) |
172 | 142 | { |
173 | 143 | TR_CommManagerPoll this = _this; |
... | ... | @@ -189,11 +159,8 @@ TR_INIT_IFACE( |
189 | 159 | TR_commManagerPollAddEndpoint, |
190 | 160 | TR_commManagerPollSelect, |
191 | 161 | TR_commManagerPollEnableWrite, |
192 | - TR_commManagerPollDisableWrite, | |
193 | 162 | TR_commManagerPollEnableRead, |
194 | - TR_commManagerPollClose, | |
195 | - TR_commManagerPollDisableWrite, | |
196 | - TR_commManagerPollDisableRead); | |
163 | + TR_commManagerPollClose); | |
197 | 164 | TR_CREATE_CLASS( |
198 | 165 | TR_CommManagerPoll, |
199 | 166 | TR_CommManager, | ... | ... |
... | ... | @@ -27,22 +27,17 @@ |
27 | 27 | #include "trevent.h" |
28 | 28 | |
29 | 29 | #include "tr/comm_manager.h" |
30 | +#include "tr/_comm_manager.h" | |
30 | 31 | |
31 | 32 | TR_EventDone |
32 | -TR_commManagerShutdown(void * _this, TR_Event event) | |
33 | +TR_commManagerShutdown(TR_CommManager this, TR_Event event) | |
33 | 34 | { |
34 | - TR_CommManager this = _this; | |
35 | - nfds_t i; | |
35 | + nfds_t i; | |
36 | 36 | |
37 | 37 | for (i=0; i<=this->max_handle; i++) { |
38 | 38 | if (this->endpoints[i]) { |
39 | - TR_eventHandlerIssueEvent( | |
40 | - (TR_EventHandler)_this, | |
41 | - TR_eventSubjectEmit( | |
42 | - (TR_EventSubject)this->endpoints[i], | |
43 | - TR_CEP_EVENT_CLOSE, | |
44 | - NULL)); | |
45 | - } | |
39 | + TR_ISSUE_IO_CLOSE_EVENT(this, this->endpoints[i]); | |
40 | + } | |
46 | 41 | } |
47 | 42 | |
48 | 43 | return TR_EVENT_DONE; | ... | ... |
... | ... | @@ -21,21 +21,34 @@ |
21 | 21 | */ |
22 | 22 | |
23 | 23 | #include "trbase.h" |
24 | -#include "trio.h" | |
24 | +#include "trdata.h" | |
25 | +#include "trevent.h" | |
25 | 26 | |
26 | 27 | #include "tr/comm_end_point.h" |
28 | +#include "tr/comm_manager.h" | |
29 | +#include "tr/_comm_manager.h" | |
27 | 30 | |
28 | -int | |
29 | -TR_cepBufferRead(TR_CommEndPoint this) | |
31 | +TR_EventDone | |
32 | +TR_commManagerShutdownRead(TR_CommManager this, TR_Event event) | |
30 | 33 | { |
31 | - TR_RemoteData data = TR_socketRecv(this->transport, this->read_chunk_size); | |
34 | + TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; | |
32 | 35 | |
33 | - if (! data) return -1; // ment to trigger a close | |
34 | - if (data == (void*)-1) return -2; // remote close... shutdown | |
35 | - if (data == TR_emptyRemoteData) return FALSE; | |
36 | + if (! TR_socketFinRd(endpoint->transport)) { | |
37 | + TR_socketShutdownRead(endpoint->transport); | |
38 | + } | |
36 | 39 | |
37 | - TR_cepAppendReadData(this, data); | |
38 | - return TRUE; | |
40 | + if (TR_socketFinRdWr(endpoint->transport)) { | |
41 | + // close | |
42 | + TR_ISSUE_IO_CLOSE_EVENT(this, event->subject); | |
43 | + } | |
44 | + | |
45 | + if (! TR_cepHasPendingData(endpoint)) { | |
46 | + TR_ISSUE_IO_SHUT_WRITE_EVENT(this, event->subject); | |
47 | + } | |
48 | + | |
49 | + TR_hashDeleteByVal(this->read, TR_hashableGetHash(event->subject)); | |
50 | + | |
51 | + return TR_EVENT_DONE; | |
39 | 52 | } |
40 | 53 | |
41 | 54 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -21,14 +21,26 @@ |
21 | 21 | */ |
22 | 22 | |
23 | 23 | #include "trbase.h" |
24 | -#include "trio.h" | |
24 | +#include "trevent.h" | |
25 | 25 | |
26 | 26 | #include "tr/comm_end_point.h" |
27 | +#include "tr/comm_manager.h" | |
28 | +#include "tr/_comm_manager.h" | |
27 | 29 | |
28 | -void | |
29 | -TR_cepAppendWriteData(TR_CommEndPoint this, TR_RemoteData data) | |
30 | +TR_EventDone | |
31 | +TR_commManagerShutdownWrite(TR_CommManager this, TR_Event event) | |
30 | 32 | { |
31 | - TR_queuePut(this->write_buffer, data); | |
33 | + TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; | |
34 | + | |
35 | + if (! TR_socketFinWr(endpoint->transport)) { | |
36 | + TR_socketShutdownWrite(endpoint->transport); | |
37 | + } | |
38 | + | |
39 | + TR_ISSUE_IO_CLOSE_EVENT(this, event->subject); | |
40 | + | |
41 | + TR_hashDeleteByVal(this->write, TR_hashableGetHash(event->subject)); | |
42 | + | |
43 | + return TR_EVENT_DONE; | |
32 | 44 | } |
33 | 45 | |
34 | 46 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -57,62 +57,74 @@ connectionDtor(void * _this) |
57 | 57 | |
58 | 58 | static |
59 | 59 | TR_ProtoMessage |
60 | -connectionNextMessage(void * _this) | |
60 | +connectionNextMessage(void * _this, TR_RemoteData * data) | |
61 | 61 | { |
62 | 62 | TR_Connection this = _this; |
63 | 63 | TR_CommEndPoint comm = _this; |
64 | - TR_RemoteData data = TR_queueGet(comm->read_buffer); | |
65 | 64 | TR_ProtoMessage ret_message = NULL; |
65 | + TR_RemoteData new_data = NULL; | |
66 | 66 | size_t end; |
67 | 67 | |
68 | - if (NULL == data) return ret_message; | |
69 | - | |
70 | - if (! this->current_message || this->current_message->ready) | |
71 | - { | |
72 | - this->current_message = | |
73 | - TR_protoCreateMessage(comm->protocol, data->remote); | |
74 | - } | |
68 | + if (*data) { | |
69 | + if (! this->current_message || this->current_message->ready) | |
70 | + { | |
71 | + this->current_message = | |
72 | + TR_protoCreateMessage(comm->protocol, (*data)->remote); | |
73 | + } | |
75 | 74 | |
76 | - end = TR_protoParse(comm->protocol, this->current_message, data); | |
75 | + end = TR_protoParse(comm->protocol, this->current_message, *data); | |
77 | 76 | |
78 | - if (end != ((TR_SizedData)data)->size) { | |
79 | 77 | /** |
80 | - * TODO | |
81 | - * This means that the parser has not consumed all of the data. | |
82 | - * We do not know the reason, but with HTTP this should only occur | |
83 | - * when the message is complete... anyway, to prevent us from | |
84 | - * looping forever because a protocol implementation is buggy | |
85 | - * we should close the connection after end was 0 the second time. | |
86 | - * This can be done by firing a close event. | |
78 | + * We define that the only valid reason for a protocol parser to not | |
79 | + * consume all data is, that the current message is complete. | |
80 | + * When a parser returns a not completely consumed data then we first | |
81 | + * check if the current message is ready. If it is we create a | |
82 | + * new data object from the remaining data and return it to the caller | |
83 | + * along with the message. The caller (which is the protocol handler) | |
84 | + * can then call this again with the remaining data. | |
85 | + * If the message is not ready we drop the data silently because there | |
86 | + * is either wrong data or a bug in the parser and the data will never | |
87 | + * be consumed correctly. | |
88 | + * INFO: Usually we do not free data here at all. We leave this to the | |
89 | + * protocol implementation. The protocol might take the data without | |
90 | + * copying it at all or if it copies it is responsible for the free too. | |
91 | + * Only if we got a wrong behaviour of the protocol we free the data | |
92 | + * ourself. | |
93 | + * IMPORTANT: The protocol should never free the data when it does not | |
94 | + * consume it completely. | |
95 | + * IMPORTANT: To keep this maintainable we must write a log message here | |
96 | + * when we drop data. This message should be a WARNING as the protocol | |
97 | + * might want to drop data intentionally... (probably this is not | |
98 | + * true and we should make it an ERROR). | |
87 | 99 | */ |
88 | - switch(end) { | |
89 | - default: | |
90 | - { | |
91 | - TR_RemoteData new_data = TR_new( | |
92 | - TR_RemoteData, | |
93 | - ((TR_SizedData)data)->data + end, | |
94 | - ((TR_SizedData)data)->size - end, | |
95 | - data->remote); | |
96 | - TR_delete(data); | |
97 | - data = new_data; | |
98 | - } | |
99 | - // intended drop through | |
100 | - | |
101 | - case 0: | |
102 | - TR_queuePutFirst(comm->read_buffer, data); | |
100 | + if (this->current_message->ready) { | |
101 | + if (end != ((TR_SizedData)*data)->size) { | |
102 | + new_data = TR_new( | |
103 | + TR_RemoteData, | |
104 | + ((TR_SizedData)*data)->data + end, | |
105 | + ((TR_SizedData)*data)->size - end, | |
106 | + (*data)->remote); | |
107 | + } | |
108 | + ret_message = this->current_message; | |
109 | + this->current_message = NULL; | |
110 | + } else { | |
111 | + if (end != ((TR_SizedData)*data)->size) { | |
112 | + TR_delete(*data); | |
113 | + TR_loggerLog( | |
114 | + TR_logger, | |
115 | + TR_LOGGER_WARNING, | |
116 | + "Drop data not consumed by protocol."); | |
117 | + } | |
103 | 118 | } |
104 | - } | |
105 | 119 | |
106 | - if (this->current_message->ready) { | |
107 | - ret_message = this->current_message; | |
108 | - this->current_message = NULL; | |
120 | + *data = new_data; | |
109 | 121 | } |
110 | 122 | |
111 | 123 | return ret_message; |
112 | 124 | } |
113 | 125 | |
114 | 126 | static |
115 | -int | |
127 | +size_t | |
116 | 128 | connectionCompose(void * _this, TR_ProtoMessage message) |
117 | 129 | { |
118 | 130 | TR_RemoteData data = |
... | ... | @@ -123,7 +135,7 @@ connectionCompose(void * _this, TR_ProtoMessage message) |
123 | 135 | } |
124 | 136 | |
125 | 137 | TR_queuePut(((TR_CommEndPoint)_this)->write_buffer, data); |
126 | - return TRUE; | |
138 | + return ((TR_SizedData)data)->size; | |
127 | 139 | } |
128 | 140 | |
129 | 141 | static | ... | ... |
... | ... | @@ -76,6 +76,15 @@ connectorAccept(void * _this, TR_Event event) |
76 | 76 | socket = TR_socketAccept((TR_TcpSocket)connection->transport); |
77 | 77 | } |
78 | 78 | |
79 | + if (! socket) { | |
80 | + TR_eventHandlerIssueEvent( | |
81 | + (TR_EventHandler)this, | |
82 | + TR_eventSubjectEmit( | |
83 | + (TR_EventSubject)connection, | |
84 | + TR_CEP_EVENT_READ_BLOCK, | |
85 | + NULL)); | |
86 | + } | |
87 | + | |
79 | 88 | return TR_EVENT_DONE; |
80 | 89 | } |
81 | 90 | ... | ... |
... | ... | @@ -51,48 +51,31 @@ datagramServiceDtor(void * _this) |
51 | 51 | |
52 | 52 | static |
53 | 53 | TR_ProtoMessage |
54 | -datagramServiceNextMessage(void * _this) | |
54 | +datagramServiceNextMessage(void * _this, TR_RemoteData * data) | |
55 | 55 | { |
56 | - TR_CommEndPoint comm = _this; | |
57 | - TR_RemoteData data = TR_queueGet(comm->read_buffer); | |
58 | - TR_ProtoMessage ret_message = NULL; | |
59 | - size_t end; | |
60 | - | |
61 | - if (NULL == data) return ret_message; | |
62 | - | |
63 | - ret_message = TR_protoCreateMessage(comm->protocol, data->remote); | |
64 | - end = TR_protoParse(comm->protocol, ret_message, data); | |
65 | - | |
66 | - if (end != ((TR_SizedData)data)->size) { | |
67 | - /** | |
68 | - * TODO | |
69 | - * This means that the parser has not consumed all of the data. | |
70 | - * We do not know the reason, but with HTTP this should only occur | |
71 | - * when the message is complete... anyway, to prevent us from | |
72 | - * looping forever because a protocol implementation is buggy | |
73 | - * we should close the connection after end was 0 the second time. | |
74 | - * This can be done by firing a close event. | |
56 | + TR_CommEndPoint comm = _this; | |
57 | + TR_ProtoMessage ret_message = NULL; | |
58 | + | |
59 | + if (*data) { | |
60 | + ret_message = TR_protoCreateMessage(comm->protocol, (*data)->remote); | |
61 | + TR_protoParse(comm->protocol, ret_message, *data); | |
62 | + | |
63 | + /* | |
64 | + * In UDP I don't care about remaining data. UDP is an all or nothing | |
65 | + * approach. If the parser is unable to create a message from the data I | |
66 | + * drop the data. | |
67 | + * Here the protocol must not free the data if it does not create a | |
68 | + * complete message from it. If a message was created the original data | |
69 | + * might or might not traval with the created message. In any case the | |
70 | + * protocol is then responsible for freeing the data. | |
75 | 71 | */ |
76 | - switch(end) { | |
77 | - default: | |
78 | - { | |
79 | - TR_RemoteData new_data = TR_new( | |
80 | - TR_RemoteData, | |
81 | - ((TR_SizedData)data)->data + end, | |
82 | - ((TR_SizedData)data)->size - end, | |
83 | - data->remote); | |
84 | - TR_delete(data); | |
85 | - data = new_data; | |
86 | - } | |
87 | - // intended drop through | |
88 | - | |
89 | - case 0: | |
90 | - TR_queuePutFirst(comm->read_buffer, data); | |
72 | + | |
73 | + if (! ret_message->ready) { | |
74 | + TR_delete(*data); | |
75 | + TR_delete(ret_message); | |
91 | 76 | } |
92 | - } | |
93 | 77 | |
94 | - if (! ret_message->ready) { | |
95 | - TR_delete(ret_message); | |
78 | + *data = NULL; | |
96 | 79 | } |
97 | 80 | |
98 | 81 | return ret_message; |
... | ... | @@ -110,7 +93,7 @@ datagramServiceCompose(void * _this, TR_ProtoMessage message) |
110 | 93 | } |
111 | 94 | |
112 | 95 | TR_queuePut(((TR_CommEndPoint)_this)->write_buffer, data); |
113 | - return TRUE; | |
96 | + return ((TR_SizedData)data)->size; | |
114 | 97 | } |
115 | 98 | |
116 | 99 | intptr_t datagramService_events[TR_CEP_EVENT_MAX + 1]; | ... | ... |
... | ... | @@ -31,17 +31,17 @@ |
31 | 31 | TR_CREATE_INTERFACE(TR_CommEndPoint, 2); |
32 | 32 | |
33 | 33 | TR_ProtoMessage |
34 | -TR_cepNextMessage(void * _this) | |
34 | +TR_cepNextMessage(void * _this, TR_RemoteData * data) | |
35 | 35 | { |
36 | 36 | TR_ProtoMessage callret; |
37 | - TR_RETCALL(_this, TR_CommEndPoint, nextMessage, callret); | |
37 | + TR_RETCALL(_this, TR_CommEndPoint, nextMessage, callret, data); | |
38 | 38 | return callret; |
39 | 39 | } |
40 | 40 | |
41 | -int | |
41 | +size_t | |
42 | 42 | TR_cepCompose(void * _this, TR_ProtoMessage message) |
43 | 43 | { |
44 | - int callret; | |
44 | + size_t callret; | |
45 | 45 | TR_RETCALL(_this, TR_CommEndPoint, compose, callret, message); |
46 | 46 | return callret; |
47 | 47 | } | ... | ... |
... | ... | @@ -29,8 +29,9 @@ |
29 | 29 | #include "tr/interface/comm_manager.h" |
30 | 30 | #include "tr/comm_end_point.h" |
31 | 31 | #include "tr/comm_manager.h" |
32 | +#include "tr/_comm_manager.h" | |
32 | 33 | |
33 | -TR_CREATE_INTERFACE(TR_CommManager, 8); | |
34 | +TR_CREATE_INTERFACE(TR_CommManager, 5); | |
34 | 35 | |
35 | 36 | void |
36 | 37 | TR_commManagerAddEndpoint(void * _this, TR_CommEndPoint endpoint) |
... | ... | @@ -48,17 +49,53 @@ TR_commManagerAddEndpoint(void * _this, TR_CommEndPoint endpoint) |
48 | 49 | : this->max_handle; |
49 | 50 | |
50 | 51 | this->endpoints[endpoint->transport->handle] = endpoint; |
52 | + | |
53 | + if (TR_INSTANCE_OF(TR_TcpSocket, endpoint->transport) | |
54 | + && ((TR_TcpSocket)endpoint->transport)->listen) { | |
55 | + TR_hashAdd(this->accept, endpoint); | |
56 | + TR_ISSUE_IO_ACC_EVENT(this, endpoint); | |
57 | + } else { | |
58 | + TR_hashAdd(this->read, endpoint); | |
59 | + TR_ISSUE_IO_READ_EVENT(this, endpoint); | |
60 | + } | |
61 | + | |
51 | 62 | TR_CALL(_this, TR_CommManager, addEndpoint, endpoint); |
52 | 63 | } |
53 | 64 | |
65 | +static | |
66 | +void | |
67 | +commManagerIssueAcceptEvents(const void * endpoint, const void * comm_manager) | |
68 | +{ | |
69 | + TR_ISSUE_IO_ACC_EVENT(comm_manager, endpoint); | |
70 | +} | |
71 | + | |
72 | +static | |
73 | +void | |
74 | +commManagerIssueWriteEvents(const void * endpoint, const void * comm_manager) | |
75 | +{ | |
76 | + TR_ISSUE_IO_WRITE_EVENT(comm_manager, endpoint); | |
77 | +} | |
78 | + | |
79 | +static | |
80 | +void | |
81 | +commManagerIssueReadEvents(const void * endpoint, const void * comm_manager) | |
82 | +{ | |
83 | + TR_ISSUE_IO_READ_EVENT(comm_manager, endpoint); | |
84 | +} | |
85 | + | |
54 | 86 | TR_EventDone |
55 | 87 | TR_commManagerSelect(void * _this, TR_Event event) |
56 | 88 | { |
89 | + TR_CommManager this = _this; | |
57 | 90 | int timeout; // milliseconds |
58 | 91 | int * timeoutptr = event->data; |
59 | 92 | TR_EventDispatcher dispatcher = (TR_EventDispatcher)event->subject; |
60 | 93 | |
61 | - if (NULL == timeoutptr) { | |
94 | + if (! (TR_hashEmpty(this->read) | |
95 | + && TR_hashEmpty(this->write) | |
96 | + && TR_hashEmpty(this->accept))) { | |
97 | + timeout = 0; | |
98 | + } else if (NULL == timeoutptr) { | |
62 | 99 | timeout = TR_eventDispatcherGetDataWaitTime(dispatcher); |
63 | 100 | } else { |
64 | 101 | timeout = *timeoutptr; |
... | ... | @@ -66,41 +103,42 @@ TR_commManagerSelect(void * _this, TR_Event event) |
66 | 103 | |
67 | 104 | TR_CALL(_this, TR_CommManager, select, event, timeout); |
68 | 105 | |
106 | + TR_hashEach(this->write, this, commManagerIssueWriteEvents); | |
107 | + TR_hashEach(this->accept, this, commManagerIssueAcceptEvents); | |
108 | + TR_hashEach(this->read, this, commManagerIssueReadEvents); | |
109 | + | |
69 | 110 | return TR_EVENT_DONE; |
70 | 111 | } |
71 | 112 | |
72 | 113 | TR_EventDone |
73 | -TR_commManagerEnableWrite(void * _this, TR_Event event) | |
114 | +TR_commManagerPollWrite(void * _this, TR_Event event) | |
74 | 115 | { |
75 | - TR_CALL(_this, TR_CommManager, enableWrite, event); | |
116 | + TR_CommManager this = _this; | |
117 | + | |
118 | + TR_hashDeleteByVal(this->write, TR_hashableGetHash(event->subject)); | |
119 | + if (! TR_socketFinWr(((TR_CommEndPoint)event->subject)->transport)) { | |
120 | + TR_CALL(_this, TR_CommManager, pollWrite, event); | |
121 | + } | |
76 | 122 | |
77 | 123 | return TR_EVENT_DONE; |
78 | 124 | } |
79 | 125 | |
80 | 126 | TR_EventDone |
81 | -TR_commManagerDisableWrite(void * _this, TR_Event event) | |
127 | +TR_commManagerPollRead(void * _this, TR_Event event) | |
82 | 128 | { |
83 | - TR_EventHandler this = _this; | |
129 | + TR_CommManager this = _this; | |
84 | 130 | TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
85 | 131 | |
86 | - TR_CALL(_this, TR_CommManager, disableWrite, event); | |
87 | - | |
88 | - if (TR_socketFinRd(endpoint->transport)) { | |
89 | - TR_eventHandlerIssueEvent( | |
90 | - this, | |
91 | - TR_eventSubjectEmit( | |
92 | - event->subject, | |
93 | - TR_CEP_EVENT_SHUT_READ, | |
94 | - NULL)); | |
132 | + if (TR_INSTANCE_OF(TR_TcpSocket, endpoint->transport) | |
133 | + && ((TR_TcpSocket)endpoint->transport)->listen) { | |
134 | + TR_hashDeleteByVal(this->accept, TR_hashableGetHash(event->subject)); | |
135 | + } else { | |
136 | + TR_hashDeleteByVal(this->read, TR_hashableGetHash(event->subject)); | |
95 | 137 | } |
96 | 138 | |
97 | - return TR_EVENT_DONE; | |
98 | -} | |
99 | - | |
100 | -TR_EventDone | |
101 | -TR_commManagerEnableRead(void * _this, TR_Event event) | |
102 | -{ | |
103 | - TR_CALL(_this, TR_CommManager, enableRead, event); | |
139 | + if (! TR_socketFinRd(endpoint->transport)) { | |
140 | + TR_CALL(_this, TR_CommManager, pollRead, event); | |
141 | + } | |
104 | 142 | |
105 | 143 | return TR_EVENT_DONE; |
106 | 144 | } |
... | ... | @@ -110,74 +148,26 @@ TR_commManagerClose(void * _this, TR_Event event) |
110 | 148 | { |
111 | 149 | TR_CommManager this = _this; |
112 | 150 | TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
113 | - | |
114 | - TR_CALL(_this, TR_CommManager, close, event); | |
151 | + int handle = endpoint->transport->handle; | |
115 | 152 | |
116 | 153 | if (! TR_socketFinRdWr(endpoint->transport)) { |
117 | 154 | TR_socketShutdown(endpoint->transport); |
118 | 155 | } |
119 | 156 | |
120 | - if (endpoint->transport->handle == this->max_handle) { | |
157 | + if (handle == this->max_handle) { | |
121 | 158 | while (! this->endpoints[--this->max_handle]); |
122 | 159 | } |
123 | 160 | |
124 | - if (this->endpoints[endpoint->transport->handle]) { | |
125 | - TR_eventSubjectFinalize( | |
126 | - (TR_EventSubject)this->endpoints[endpoint->transport->handle]); | |
127 | - this->endpoints[endpoint->transport->handle] = NULL; | |
128 | - } | |
129 | - | |
130 | - return TR_EVENT_DONE; | |
131 | -} | |
132 | - | |
133 | -TR_EventDone | |
134 | -TR_commManagerShutdownRead(void * _this, TR_Event event) | |
135 | -{ | |
136 | - TR_CALL(_this, TR_CommManager, shutdownRead, event); | |
137 | - | |
138 | - if (! TR_socketFinRd(((TR_CommEndPoint)event->subject)->transport)) { | |
139 | - TR_socketShutdownRead(((TR_CommEndPoint)event->subject)->transport); | |
161 | + if (this->endpoints[handle]) { | |
162 | + TR_eventSubjectFinalize((TR_EventSubject)this->endpoints[handle]); | |
163 | + this->endpoints[handle] = NULL; | |
164 | + TR_hashDeleteByVal(this->write, TR_hashableGetHash(endpoint)); | |
165 | + TR_hashDeleteByVal(this->read, TR_hashableGetHash(endpoint)); | |
140 | 166 | } |
141 | 167 | |
142 | - if (TR_socketFinRdWr(((TR_CommEndPoint)event->subject)->transport)) { | |
143 | - // close | |
144 | - TR_eventHandlerIssueEvent( | |
145 | - (TR_EventHandler)_this, | |
146 | - TR_eventSubjectEmit( | |
147 | - event->subject, | |
148 | - TR_CEP_EVENT_CLOSE, | |
149 | - NULL)); | |
150 | - } | |
151 | - | |
152 | - if (! TR_cepHasPendingData((TR_CommEndPoint)event->subject)) { | |
153 | - TR_eventHandlerIssueEvent( | |
154 | - (TR_EventHandler)_this, | |
155 | - TR_eventSubjectEmit( | |
156 | - event->subject, | |
157 | - TR_CEP_EVENT_SHUT_WRITE, | |
158 | - NULL)); | |
159 | - } | |
160 | - | |
161 | - return TR_EVENT_DONE; | |
162 | -} | |
163 | - | |
164 | -TR_EventDone | |
165 | -TR_commManagerShutdownWrite(void * _this, TR_Event event) | |
166 | -{ | |
167 | - TR_CALL(_this, TR_CommManager, shutdownWrite, event); | |
168 | - | |
169 | - if (! TR_socketFinWr(((TR_CommEndPoint)event->subject)->transport)) { | |
170 | - TR_socketShutdownWrite(((TR_CommEndPoint)event->subject)->transport); | |
171 | - } | |
168 | + TR_CALL(_this, TR_CommManager, close, event); | |
172 | 169 | |
173 | - if (TR_socketFinRdWr(((TR_CommEndPoint)event->subject)->transport)) { | |
174 | - TR_eventHandlerIssueEvent( | |
175 | - (TR_EventHandler)_this, | |
176 | - TR_eventSubjectEmit( | |
177 | - event->subject, | |
178 | - TR_CEP_EVENT_CLOSE, | |
179 | - NULL)); | |
180 | - } | |
170 | + this->endpoints[handle] = NULL; | |
181 | 171 | |
182 | 172 | return TR_EVENT_DONE; |
183 | 173 | } | ... | ... |
... | ... | @@ -21,9 +21,12 @@ |
21 | 21 | */ |
22 | 22 | |
23 | 23 | #include <unistd.h> |
24 | +#include <inttypes.h> | |
25 | +#include <stdio.h> | |
24 | 26 | |
25 | 27 | #include "trbase.h" |
26 | 28 | #include "trevent.h" |
29 | +#include "trio.h" | |
27 | 30 | |
28 | 31 | #include "tr/io_handler.h" |
29 | 32 | #include "tr/comm_end_point.h" |
... | ... | @@ -44,40 +47,47 @@ static |
44 | 47 | TR_EventDone |
45 | 48 | ioHandlerRead(void * _this, TR_Event event) |
46 | 49 | { |
47 | - TR_Event revent; | |
50 | + TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; | |
51 | + TR_Event revent; | |
52 | + TR_RemoteData data; | |
48 | 53 | |
49 | - switch (TR_cepBufferRead((TR_CommEndPoint)event->subject)) { | |
50 | - case FALSE: // EAGAIN | |
51 | - revent = TR_eventSubjectEmit( | |
52 | - event->subject, | |
53 | - TR_CEP_EVENT_READ_BLOCK, | |
54 | - NULL); | |
55 | - break; | |
54 | + if (endpoint->write_buffer_size < CEP_WRITE_BUFFER_THRESHOLD) { | |
55 | + switch (TR_commEndPointRead(endpoint, &data)) { | |
56 | + case FALSE: // EAGAIN | |
57 | + revent = TR_eventSubjectEmit( | |
58 | + event->subject, | |
59 | + TR_CEP_EVENT_READ_BLOCK, | |
60 | + NULL); | |
61 | + break; | |
56 | 62 | |
57 | - case -1: // error | |
58 | - revent = TR_eventSubjectEmit( | |
59 | - event->subject, | |
60 | - TR_CEP_EVENT_CLOSE, | |
61 | - NULL); | |
62 | - break; | |
63 | + case -1: // error | |
64 | + revent = TR_eventSubjectEmit( | |
65 | + event->subject, | |
66 | + TR_CEP_EVENT_CLOSE, | |
67 | + NULL); | |
68 | + break; | |
63 | 69 | |
64 | - default: | |
65 | - case -2: // remote close | |
66 | - revent = TR_eventSubjectEmit( | |
67 | - event->subject, | |
68 | - TR_CEP_EVENT_SHUT_READ, | |
69 | - NULL); | |
70 | - break; | |
70 | + default: | |
71 | + case -2: // remote close | |
72 | + revent = TR_eventSubjectEmit( | |
73 | + event->subject, | |
74 | + TR_CEP_EVENT_SHUT_READ, | |
75 | + NULL); | |
76 | + break; | |
71 | 77 | |
72 | - case TRUE: | |
73 | - revent = TR_eventSubjectEmit( | |
74 | - event->subject, | |
75 | - TR_CEP_EVENT_NEW_DATA, | |
76 | - NULL); | |
77 | - break; | |
78 | - } | |
78 | + case -3: // read limit | |
79 | + return TR_EVENT_DONE; | |
79 | 80 | |
80 | - TR_eventHandlerIssueEvent((TR_EventHandler)_this, revent); | |
81 | + case TRUE: | |
82 | + revent = TR_eventSubjectEmit( | |
83 | + event->subject, | |
84 | + TR_CEP_EVENT_NEW_DATA, | |
85 | + data); | |
86 | + break; | |
87 | + } | |
88 | + | |
89 | + TR_eventHandlerIssueEvent((TR_EventHandler)_this, revent); | |
90 | + } | |
81 | 91 | |
82 | 92 | return TR_EVENT_DONE; |
83 | 93 | } |
... | ... | @@ -86,15 +96,15 @@ static |
86 | 96 | TR_EventDone |
87 | 97 | ioHandlerWrite(void * _this, TR_Event event) |
88 | 98 | { |
89 | - TR_Event revent = NULL, | |
90 | - close_event = NULL; | |
99 | + TR_Event revent = NULL; | |
91 | 100 | TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
101 | + size_t written; | |
92 | 102 | |
93 | - switch (TR_cepWriteBuffered(endpoint)) { | |
103 | + switch (TR_cepWriteBuffered(endpoint, &written)) { | |
94 | 104 | case FALSE: // EAGAIN |
95 | 105 | revent = TR_eventSubjectEmit( |
96 | 106 | event->subject, |
97 | - TR_CEP_EVENT_PENDING_DATA, // is WRITE_BLOCK | |
107 | + TR_CEP_EVENT_WRITE_BLOCK, | |
98 | 108 | NULL); |
99 | 109 | break; |
100 | 110 | |
... | ... | @@ -112,24 +122,31 @@ ioHandlerWrite(void * _this, TR_Event event) |
112 | 122 | NULL); |
113 | 123 | break; |
114 | 124 | |
125 | + case -3: // remote end not ready | |
126 | + break; | |
127 | + | |
128 | + case -4: // no more data to send | |
129 | + revent = TR_eventSubjectEmit( | |
130 | + event->subject, | |
131 | + TR_CEP_EVENT_DATA_END, | |
132 | + NULL); | |
133 | + break; | |
134 | + | |
115 | 135 | default: |
116 | - if (! TR_cepHasPendingData((TR_CommEndPoint)event->subject)) { | |
136 | + // TODO This still looks wrong... | |
137 | + if (TRUE == endpoint->do_close) { | |
117 | 138 | revent = TR_eventSubjectEmit( |
118 | 139 | event->subject, |
119 | - TR_CEP_EVENT_END_DATA, | |
140 | + TR_CEP_EVENT_CLOSE, | |
120 | 141 | NULL); |
121 | - | |
122 | - if (TRUE == ((TR_CommEndPoint)event->subject)->do_close) { | |
123 | - close_event = TR_eventSubjectEmit( | |
124 | - event->subject, | |
125 | - TR_CEP_EVENT_CLOSE, | |
126 | - NULL); | |
127 | - } | |
128 | 142 | } |
129 | 143 | } |
130 | 144 | |
131 | - TR_eventHandlerIssueEvent((TR_EventHandler)_this, revent); | |
132 | - TR_eventHandlerIssueEvent((TR_EventHandler)_this, close_event); | |
145 | + endpoint->write_buffer_size -= written; | |
146 | + | |
147 | + if (revent) { | |
148 | + TR_eventHandlerIssueEvent((TR_EventHandler)_this, revent); | |
149 | + } | |
133 | 150 | |
134 | 151 | return TR_EVENT_DONE; |
135 | 152 | } |
... | ... | @@ -141,13 +158,12 @@ ioHandlerCvInit(TR_class_ptr cls) |
141 | 158 | TR_EVENT_HANDLER_SET_METHOD( |
142 | 159 | cls, |
143 | 160 | TR_CommEndPoint, |
144 | - TR_CEP_EVENT_READ_READY, | |
161 | + TR_CEP_EVENT_DO_READ, | |
145 | 162 | ioHandlerRead); |
146 | - | |
147 | 163 | TR_EVENT_HANDLER_SET_METHOD( |
148 | 164 | cls, |
149 | 165 | TR_CommEndPoint, |
150 | - TR_CEP_EVENT_WRITE_READY, | |
166 | + TR_CEP_EVENT_DO_WRITE, | |
151 | 167 | ioHandlerWrite); |
152 | 168 | } |
153 | 169 | ... | ... |
... | ... | @@ -51,9 +51,10 @@ protocolHandlerParse(void * _this, TR_Event event) |
51 | 51 | * TODO No upgrade for now. Add it later on. |
52 | 52 | */ |
53 | 53 | TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
54 | - TR_ProtoMessage message = TR_cepNextMessage(endpoint); | |
54 | + TR_RemoteData data = event->data; | |
55 | + TR_ProtoMessage message; | |
55 | 56 | |
56 | - if (message) { | |
57 | + while ((message = TR_cepNextMessage(endpoint, &data))) { | |
57 | 58 | TR_eventHandlerIssueEvent( |
58 | 59 | (TR_EventHandler)_this, |
59 | 60 | TR_eventSubjectEmit( |
... | ... | @@ -62,8 +63,8 @@ protocolHandlerParse(void * _this, TR_Event event) |
62 | 63 | message)); |
63 | 64 | |
64 | 65 | if (message->close) { |
65 | - // also check that we are a response. Well this is how it is done | |
66 | - // in the python code... | |
66 | + // also check that we are a response. Well this is | |
67 | + // how it is done in the python code... | |
67 | 68 | TR_cepSetClose(endpoint); |
68 | 69 | } |
69 | 70 | } |
... | ... | @@ -77,6 +78,7 @@ protocolHandlerCompose(void * _this, TR_Event event) |
77 | 78 | { |
78 | 79 | TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
79 | 80 | TR_ProtoMessage message = (TR_ProtoMessage)event->data; |
81 | + size_t message_size; | |
80 | 82 | |
81 | 83 | if (message->close) { |
82 | 84 | // also check that we are a response. Well this is how it is done |
... | ... | @@ -84,13 +86,17 @@ protocolHandlerCompose(void * _this, TR_Event event) |
84 | 86 | TR_cepSetClose(endpoint); |
85 | 87 | } |
86 | 88 | |
87 | - if (TR_cepCompose(endpoint, message)) { | |
88 | - TR_Event _event = TR_eventSubjectEmit( | |
89 | - event->subject, | |
90 | - TR_CEP_EVENT_WRITE_READY, | |
91 | - NULL); | |
89 | + if ((message_size = TR_cepCompose(endpoint, message))) { | |
90 | + endpoint->write_buffer_size += message_size; | |
92 | 91 | |
93 | - TR_eventHandlerIssueEvent((TR_EventHandler)_this, _event); | |
92 | + if (endpoint->write_buffer->nmsg == 1) { | |
93 | + TR_eventHandlerIssueEvent( | |
94 | + (TR_EventHandler)_this, | |
95 | + TR_eventSubjectEmit( | |
96 | + event->subject, | |
97 | + TR_CEP_EVENT_DATA_READY, | |
98 | + NULL)); | |
99 | + } | |
94 | 100 | } |
95 | 101 | TR_delete(message); |
96 | 102 | |
... | ... | @@ -112,18 +118,16 @@ protocolHandlerCvInit(TR_class_ptr cls) |
112 | 118 | TR_CommEndPoint, |
113 | 119 | TR_CEP_EVENT_NEW_DATA, |
114 | 120 | protocolHandlerParse); |
115 | - | |
116 | 121 | TR_EVENT_HANDLER_SET_METHOD( |
117 | 122 | cls, |
118 | 123 | TR_CommEndPoint, |
119 | - TR_CEP_EVENT_SEND_MSG, | |
124 | + TR_CEP_EVENT_MSG_READY, | |
120 | 125 | protocolHandlerCompose); |
121 | - | |
122 | - TR_EVENT_HANDLER_SET_METHOD( | |
123 | - cls, | |
124 | - TR_CommEndPoint, | |
125 | - TR_CEP_EVENT_UPGRADE, | |
126 | - protocolHandlerUpgrade); | |
126 | +// TR_EVENT_HANDLER_SET_METHOD( | |
127 | +// cls, | |
128 | +// TR_CommEndPoint, | |
129 | +// TR_CEP_EVENT_UPGRADE, | |
130 | +// protocolHandlerUpgrade); | |
127 | 131 | } |
128 | 132 | |
129 | 133 | TR_INSTANCE(TR_Hash, protocolHandlerEventMethods); | ... | ... |
... | ... | @@ -39,7 +39,7 @@ testHandlerNewMessage(TR_EventHandler this, TR_Event event) |
39 | 39 | |
40 | 40 | _event = TR_eventSubjectEmit( |
41 | 41 | event->subject, |
42 | - TR_CEP_EVENT_SEND_MSG, | |
42 | + TR_CEP_EVENT_MSG_READY, | |
43 | 43 | event->data); |
44 | 44 | |
45 | 45 | TR_eventHandlerIssueEvent((TR_EventHandler)this, _event); |
... | ... | @@ -56,14 +56,14 @@ testHandlerClose(TR_EventHandler this, TR_Event event) |
56 | 56 | return TR_EVENT_PENDING; |
57 | 57 | } |
58 | 58 | |
59 | -static | |
60 | -TR_EventDone | |
61 | -testHandlerUpgrade(TR_EventHandler this, TR_Event event) | |
62 | -{ | |
63 | - printf("upgrade: %"PRIdPTR"\n", event->id); | |
64 | - | |
65 | - return TR_EVENT_PENDING; | |
66 | -} | |
59 | +//static | |
60 | +//TR_EventDone | |
61 | +//testHandlerUpgrade(TR_EventHandler this, TR_Event event) | |
62 | +//{ | |
63 | +// printf("upgrade: %"PRIdPTR"\n", event->id); | |
64 | +// | |
65 | +// return TR_EVENT_PENDING; | |
66 | +//} | |
67 | 67 | |
68 | 68 | static |
69 | 69 | int |
... | ... | @@ -101,11 +101,11 @@ testHandlerCvInit(TR_class_ptr class) |
101 | 101 | TR_CommEndPoint, |
102 | 102 | TR_CEP_EVENT_CLOSE, |
103 | 103 | testHandlerClose); |
104 | - TR_EVENT_HANDLER_SET_METHOD( | |
105 | - class, | |
106 | - TR_CommEndPoint, | |
107 | - TR_CEP_EVENT_UPGRADE, | |
108 | - testHandlerUpgrade); | |
104 | +// TR_EVENT_HANDLER_SET_METHOD( | |
105 | +// class, | |
106 | +// TR_CommEndPoint, | |
107 | +// TR_CEP_EVENT_UPGRADE, | |
108 | +// testHandlerUpgrade); | |
109 | 109 | } |
110 | 110 | |
111 | 111 | TR_INSTANCE(TR_Hash, testHandlerEventMethods); | ... | ... |
1 | 1 | #!/bin/sh |
2 | 2 | |
3 | +BS=8192 | |
4 | +COUNT=25000 | |
5 | +CONCURENT=200 | |
6 | +IP="192.168.2.13" | |
3 | 7 | pids="" |
4 | 8 | i=0 |
5 | -while [ $i -lt 800 ] | |
9 | + | |
10 | +while [ $i -lt ${CONCURENT} ] | |
6 | 11 | do |
7 | - dd if=/dev/zero bs=8192 count=2500 | nc 192.168.2.13 5678 & | |
12 | + dd if=/dev/zero bs=${BS} count=${COUNT} | nc ${IP} 5678 >/dev/null & | |
8 | 13 | pids="${pids} $!" |
9 | 14 | i=$((i + 1)) |
10 | 15 | done | ... | ... |
Please
register
or
login
to post a comment