trema 0.4.5 → 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -4
- data/Guardfile +8 -0
- data/Rakefile +2 -1
- data/bin/trema +4 -0
- data/cruise.rb +1 -1
- data/features/core/switch_manager.feature +2 -2
- data/features/examples/message.vendor-action.feature +2 -2
- data/features/examples/message.vendor-stats-request.feature +20 -0
- data/features/trema_commands/kill.feature +4 -0
- data/features/trema_commands/killall.feature +1 -0
- data/features/trema_commands/run.feature +20 -1
- data/ruby/trema/command/run.rb +4 -0
- data/ruby/trema/default_openflow_channel_port.rb +26 -0
- data/ruby/trema/dsl/configuration.rb +2 -1
- data/ruby/trema/open-vswitch.rb +2 -4
- data/ruby/trema/stats-reply.c +10 -1
- data/ruby/trema/stats-request.c +34 -1
- data/ruby/trema/vendor-stats-reply.rb +6 -2
- data/ruby/trema/version.rb +1 -1
- data/spec/trema/dsl/runner_spec.rb +1 -1
- data/spec/trema/dsl/syntax_spec.rb +1 -1
- data/spec/trema/shell/vswitch_spec.rb +1 -1
- data/spec/trema/stats-reply_spec.rb +2 -1
- data/spec/trema/stats-request_spec.rb +11 -0
- data/src/examples/cbench_switch/cbench-switch.rb +1 -0
- data/src/examples/cbench_switch/cbench_switch.c +1 -1
- data/src/examples/openflow_message/vendor-action.rb +4 -4
- data/src/examples/openflow_message/vendor-stats-request.rb +66 -0
- data/src/examples/simple_router/arp-table.rb +6 -17
- data/src/examples/simple_router/interface.rb +20 -29
- data/src/examples/simple_router/routing-table.rb +15 -22
- data/src/examples/simple_router/simple-router.rb +75 -64
- data/src/lib/chibach.c +3 -2
- data/src/lib/event_handler.c +55 -23
- data/src/lib/event_handler.h +0 -5
- data/src/lib/external_callback.c +126 -0
- data/src/lib/external_callback.h +46 -0
- data/src/lib/messenger.c +58 -35
- data/src/lib/openflow_message.c +32 -11
- data/src/lib/trema.c +13 -7
- data/src/lib/trema.h +1 -0
- data/src/lib/utility.c +13 -2
- data/src/switch_manager/secure_channel_receiver.c +6 -1
- data/src/switch_manager/switch.c +27 -26
- data/src/switch_manager/switch_manager.c +31 -10
- data/src/tremashark/packet_capture.c +3 -2
- data/src/tremashark/tremashark.c +2 -2
- data/trema.gemspec +1 -1
- data/unittests/lib/external_callback_test.c +282 -0
- data/unittests/lib/messenger_test.c +22 -0
- data/unittests/lib/openflow_message_test.c +1 -1
- data/unittests/lib/trema_test.c +1 -1
- data/unittests/switch_manager/switch_manager_test.c +3 -3
- metadata +12 -6
- data/src/examples/simple_router/router-utils.rb +0 -211
data/src/lib/chibach.c
CHANGED
@@ -33,6 +33,7 @@
|
|
33
33
|
#include <unistd.h>
|
34
34
|
#include "chibach.h"
|
35
35
|
#include "chibach_private.h"
|
36
|
+
#include "external_callback.h"
|
36
37
|
#include "daemon.h"
|
37
38
|
#include "doubly_linked_list.h"
|
38
39
|
#include "log.h"
|
@@ -191,7 +192,7 @@ parse_argv( int *argc, char ***argv ) {
|
|
191
192
|
|
192
193
|
run_as_daemon = false;
|
193
194
|
controller.ip = 0x7f000001;
|
194
|
-
controller.port =
|
195
|
+
controller.port = 6653;
|
195
196
|
|
196
197
|
for ( int i = 0; i < *argc; ++i ) {
|
197
198
|
new_argv[ i ] = ( *argv )[ i ];
|
@@ -286,7 +287,7 @@ set_exit_handler() {
|
|
286
287
|
|
287
288
|
static void
|
288
289
|
set_dump_stats_as_external_callback() {
|
289
|
-
|
290
|
+
push_external_callback( dump_stats );
|
290
291
|
}
|
291
292
|
|
292
293
|
|
data/src/lib/event_handler.c
CHANGED
@@ -23,6 +23,7 @@
|
|
23
23
|
#include <unistd.h>
|
24
24
|
#include "checks.h"
|
25
25
|
#include "event_handler.h"
|
26
|
+
#include "external_callback.h"
|
26
27
|
#include "log.h"
|
27
28
|
#include "timer.h"
|
28
29
|
|
@@ -61,6 +62,30 @@ extern bool mock_add_periodic_event_callback( const time_t seconds, void ( *call
|
|
61
62
|
#define execute_timer_events mock_execute_timer_events
|
62
63
|
extern void mock_execute_timer_events( int *next_timeout_usec );
|
63
64
|
|
65
|
+
#ifdef init_external_callback
|
66
|
+
#undef init_external_callback
|
67
|
+
#endif
|
68
|
+
#define init_external_callback mock_init_external_callback
|
69
|
+
extern void mock_init_external_callback( void );
|
70
|
+
|
71
|
+
#ifdef finalize_external_callback
|
72
|
+
#undef finalize_external_callback
|
73
|
+
#endif
|
74
|
+
#define finalize_external_callback mock_finalize_external_callback
|
75
|
+
extern void mock_finalize_external_callback( void );
|
76
|
+
|
77
|
+
#ifdef push_external_callback
|
78
|
+
#undef push_external_callback
|
79
|
+
#endif
|
80
|
+
#define push_external_callback mock_push_external_callback
|
81
|
+
extern void mock_push_external_callback( external_callback_t callback );
|
82
|
+
|
83
|
+
#ifdef run_external_callback
|
84
|
+
#undef run_external_callback
|
85
|
+
#endif
|
86
|
+
#define run_external_callback mock_run_external_callback
|
87
|
+
extern void mock_run_external_callback( void );
|
88
|
+
|
64
89
|
#endif // UNIT_TESTING
|
65
90
|
|
66
91
|
|
@@ -94,19 +119,19 @@ fd_set current_write_set;
|
|
94
119
|
|
95
120
|
int fd_set_size = 0;
|
96
121
|
|
97
|
-
external_callback_t external_callback = ( external_callback_t ) NULL;
|
98
|
-
|
99
|
-
|
100
122
|
static void
|
101
123
|
_init_event_handler() {
|
102
124
|
event_last = event_list;
|
103
|
-
event_handler_state = EVENT_HANDLER_INITIALIZED;
|
104
125
|
|
105
126
|
memset( event_list, 0, sizeof( event_fd ) * FD_SETSIZE );
|
106
127
|
memset( event_fd_set, 0, sizeof( event_fd * ) * FD_SETSIZE );
|
107
128
|
|
108
129
|
FD_ZERO( &event_read_set );
|
109
130
|
FD_ZERO( &event_write_set );
|
131
|
+
|
132
|
+
init_external_callback();
|
133
|
+
|
134
|
+
event_handler_state = EVENT_HANDLER_INITIALIZED;
|
110
135
|
}
|
111
136
|
void ( *init_event_handler )() = _init_event_handler;
|
112
137
|
|
@@ -120,18 +145,15 @@ _finalize_event_handler() {
|
|
120
145
|
}
|
121
146
|
|
122
147
|
event_handler_state = EVENT_HANDLER_FINALIZED;
|
148
|
+
|
149
|
+
finalize_external_callback();
|
123
150
|
}
|
124
151
|
void ( *finalize_event_handler )() = _finalize_event_handler;
|
125
152
|
|
126
153
|
|
127
154
|
static bool
|
128
155
|
_run_event_handler_once( int timeout_usec ) {
|
129
|
-
|
130
|
-
external_callback_t callback = external_callback;
|
131
|
-
external_callback = NULL;
|
132
|
-
|
133
|
-
callback();
|
134
|
-
}
|
156
|
+
run_external_callback();
|
135
157
|
|
136
158
|
memcpy( ¤t_read_set, &event_read_set, sizeof( fd_set ) );
|
137
159
|
memcpy( ¤t_write_set, &event_write_set, sizeof( fd_set ) );
|
@@ -143,6 +165,7 @@ _run_event_handler_once( int timeout_usec ) {
|
|
143
165
|
|
144
166
|
if ( set_count == -1 ) {
|
145
167
|
if ( errno == EINTR ) {
|
168
|
+
run_external_callback();
|
146
169
|
return true;
|
147
170
|
}
|
148
171
|
error( "Failed to select ( errno = %s [%d] ).", strerror( errno ), errno );
|
@@ -151,11 +174,13 @@ _run_event_handler_once( int timeout_usec ) {
|
|
151
174
|
}
|
152
175
|
else if ( set_count == 0 ) {
|
153
176
|
// timed out
|
177
|
+
run_external_callback();
|
154
178
|
return true;
|
155
179
|
}
|
156
180
|
|
157
|
-
|
181
|
+
run_external_callback();
|
158
182
|
|
183
|
+
event_fd *event_itr = event_list;
|
159
184
|
while ( event_itr < event_last ) {
|
160
185
|
event_fd current_event = *event_itr;
|
161
186
|
|
@@ -163,6 +188,23 @@ _run_event_handler_once( int timeout_usec ) {
|
|
163
188
|
current_event.write_callback( current_event.fd, current_event.write_data );
|
164
189
|
}
|
165
190
|
|
191
|
+
// In the rare cases the current fd is closed, a new one is opened
|
192
|
+
// with the same fd and is put in the same location we can just
|
193
|
+
// wait for the next select call.
|
194
|
+
if ( current_event.fd == event_itr->fd ) {
|
195
|
+
event_itr = event_itr + 1;
|
196
|
+
}
|
197
|
+
else {
|
198
|
+
debug( "run_event_handler_once: event fd is changed ( current = %d, new = %d )", current_event.fd, event_itr->fd );
|
199
|
+
}
|
200
|
+
}
|
201
|
+
|
202
|
+
run_external_callback();
|
203
|
+
|
204
|
+
event_itr = event_list;
|
205
|
+
while ( event_itr < event_last ) {
|
206
|
+
event_fd current_event = *event_itr;
|
207
|
+
|
166
208
|
if ( FD_ISSET( current_event.fd, ¤t_read_set ) ) {
|
167
209
|
current_event.read_callback( current_event.fd, current_event.read_data );
|
168
210
|
}
|
@@ -178,6 +220,8 @@ _run_event_handler_once( int timeout_usec ) {
|
|
178
220
|
}
|
179
221
|
}
|
180
222
|
|
223
|
+
run_external_callback();
|
224
|
+
|
181
225
|
return true;
|
182
226
|
}
|
183
227
|
bool ( *run_event_handler_once )( int ) = _run_event_handler_once;
|
@@ -367,18 +411,6 @@ _writable( int fd ) {
|
|
367
411
|
bool ( *writable )( int fd ) = _writable;
|
368
412
|
|
369
413
|
|
370
|
-
static bool
|
371
|
-
_set_external_callback( external_callback_t callback ) {
|
372
|
-
if ( external_callback != NULL ) {
|
373
|
-
return false;
|
374
|
-
}
|
375
|
-
|
376
|
-
external_callback = callback;
|
377
|
-
return true;
|
378
|
-
}
|
379
|
-
bool ( *set_external_callback )( external_callback_t callback ) = _set_external_callback;
|
380
|
-
|
381
|
-
|
382
414
|
/*
|
383
415
|
* Local variables:
|
384
416
|
* c-basic-offset: 2
|
data/src/lib/event_handler.h
CHANGED
@@ -27,7 +27,6 @@
|
|
27
27
|
|
28
28
|
|
29
29
|
typedef void ( *event_fd_callback )( int, void *data );
|
30
|
-
typedef void ( *external_callback_t )( void );
|
31
30
|
|
32
31
|
extern void ( *init_event_handler )();
|
33
32
|
extern void ( *finalize_event_handler )();
|
@@ -46,10 +45,6 @@ extern void ( *set_writable )( int fd, bool state );
|
|
46
45
|
extern bool ( *readable )( int fd );
|
47
46
|
extern bool ( *writable )( int fd );
|
48
47
|
|
49
|
-
// Optional functions for event handlers to implement, must be signal
|
50
|
-
// safe. Leave as NULL if not supported.
|
51
|
-
extern bool ( *set_external_callback )( external_callback_t callback );
|
52
|
-
|
53
48
|
|
54
49
|
#endif // EVENT_HANDLER_H
|
55
50
|
|
@@ -0,0 +1,126 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) 2013 NEC Corporation
|
3
|
+
*
|
4
|
+
* This program is free software; you can redistribute it and/or modify
|
5
|
+
* it under the terms of the GNU General Public License, version 2, as
|
6
|
+
* published by the Free Software Foundation.
|
7
|
+
*
|
8
|
+
* This program is distributed in the hope that it will be useful,
|
9
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
* GNU General Public License for more details.
|
12
|
+
*
|
13
|
+
* You should have received a copy of the GNU General Public License along
|
14
|
+
* with this program; if not, write to the Free Software Foundation, Inc.,
|
15
|
+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
16
|
+
*/
|
17
|
+
|
18
|
+
|
19
|
+
#include <assert.h>
|
20
|
+
#include "external_callback.h"
|
21
|
+
#include "log.h"
|
22
|
+
#include "wrapper.h"
|
23
|
+
|
24
|
+
#ifdef UNIT_TESTING
|
25
|
+
|
26
|
+
#ifdef xcalloc
|
27
|
+
#undef xcalloc
|
28
|
+
#endif
|
29
|
+
#define xcalloc mock_xcalloc
|
30
|
+
extern void *mock_xcalloc( size_t nmemb, size_t size );
|
31
|
+
|
32
|
+
#ifdef xfree
|
33
|
+
#undef xfree
|
34
|
+
#endif
|
35
|
+
#define xfree mock_xfree
|
36
|
+
extern void mock_xfree( void *ptr );
|
37
|
+
|
38
|
+
#ifdef debug
|
39
|
+
#undef debug
|
40
|
+
#endif
|
41
|
+
#define debug mock_debug
|
42
|
+
extern void mock_debug( const char *format, ... );
|
43
|
+
|
44
|
+
#define static
|
45
|
+
|
46
|
+
#endif // UNIT_TESTING
|
47
|
+
|
48
|
+
|
49
|
+
typedef struct {
|
50
|
+
external_callback_t *buffer;
|
51
|
+
unsigned int size;
|
52
|
+
unsigned int write_position;
|
53
|
+
unsigned int read_position;
|
54
|
+
} ring_buffer;
|
55
|
+
|
56
|
+
static const unsigned int MAX_EXTERNAL_CALLBACK = 16;
|
57
|
+
static ring_buffer *external_callbacks = NULL;
|
58
|
+
|
59
|
+
|
60
|
+
static void
|
61
|
+
_init_external_callback() {
|
62
|
+
assert( external_callbacks == NULL );
|
63
|
+
|
64
|
+
external_callbacks = xcalloc( 1, sizeof( ring_buffer ) );
|
65
|
+
external_callbacks->buffer = xcalloc( MAX_EXTERNAL_CALLBACK, sizeof( external_callback_t * ) );
|
66
|
+
external_callbacks->size = MAX_EXTERNAL_CALLBACK;
|
67
|
+
}
|
68
|
+
void ( *init_external_callback )() = _init_external_callback;
|
69
|
+
|
70
|
+
|
71
|
+
static void
|
72
|
+
_finalize_external_callback() {
|
73
|
+
assert( external_callbacks != NULL );
|
74
|
+
assert( external_callbacks->buffer != NULL );
|
75
|
+
|
76
|
+
xfree( external_callbacks->buffer );
|
77
|
+
xfree( external_callbacks );
|
78
|
+
external_callbacks = NULL;
|
79
|
+
}
|
80
|
+
void ( *finalize_external_callback )() = _finalize_external_callback;
|
81
|
+
|
82
|
+
|
83
|
+
static bool
|
84
|
+
_push_external_callback( external_callback_t callback ) {
|
85
|
+
if ( callback == NULL ) {
|
86
|
+
return false;
|
87
|
+
}
|
88
|
+
if ( external_callbacks == NULL ) {
|
89
|
+
return false;
|
90
|
+
}
|
91
|
+
assert( external_callbacks->buffer != NULL );
|
92
|
+
|
93
|
+
debug( "push_external_callback: %p", callback );
|
94
|
+
unsigned int write_pos = __sync_fetch_and_add( &external_callbacks->write_position, 1 ) % external_callbacks->size;
|
95
|
+
assert( __sync_bool_compare_and_swap( &( external_callbacks->buffer[ write_pos ] ), NULL, callback ) );
|
96
|
+
|
97
|
+
return true;
|
98
|
+
}
|
99
|
+
bool ( *push_external_callback )( external_callback_t callback ) = _push_external_callback;
|
100
|
+
|
101
|
+
|
102
|
+
static void
|
103
|
+
_run_external_callback() {
|
104
|
+
assert( external_callbacks != NULL );
|
105
|
+
assert( external_callbacks->buffer != NULL );
|
106
|
+
|
107
|
+
while ( external_callbacks->write_position != external_callbacks->read_position ) {
|
108
|
+
unsigned int read_pos = external_callbacks->read_position % external_callbacks->size;
|
109
|
+
external_callback_t callback = external_callbacks->buffer[ read_pos ];
|
110
|
+
assert( callback != NULL );
|
111
|
+
external_callbacks->buffer[ read_pos ] = NULL;
|
112
|
+
external_callbacks->read_position++;
|
113
|
+
debug( "run_external_callback: %p ( write_position = %u, read_position = %u )", callback,
|
114
|
+
external_callbacks->write_position, external_callbacks->read_position );
|
115
|
+
callback();
|
116
|
+
}
|
117
|
+
}
|
118
|
+
void ( *run_external_callback )() = _run_external_callback;
|
119
|
+
|
120
|
+
|
121
|
+
/*
|
122
|
+
* Local variables:
|
123
|
+
* c-basic-offset: 2
|
124
|
+
* indent-tabs-mode: nil
|
125
|
+
* End:
|
126
|
+
*/
|
@@ -0,0 +1,46 @@
|
|
1
|
+
/*
|
2
|
+
* External callback implementation
|
3
|
+
*
|
4
|
+
* Copyright (C) 2013 NEC Corporation
|
5
|
+
*
|
6
|
+
* This program is free software; you can redistribute it and/or modify
|
7
|
+
* it under the terms of the GNU General Public License, version 2, as
|
8
|
+
* published by the Free Software Foundation.
|
9
|
+
*
|
10
|
+
* This program is distributed in the hope that it will be useful,
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
* GNU General Public License for more details.
|
14
|
+
*
|
15
|
+
* You should have received a copy of the GNU General Public License along
|
16
|
+
* with this program; if not, write to the Free Software Foundation, Inc.,
|
17
|
+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
18
|
+
*/
|
19
|
+
|
20
|
+
|
21
|
+
#ifndef EXTERNAL_CALLBACK_H
|
22
|
+
#define EXTERNAL_CALLBACK_H
|
23
|
+
|
24
|
+
|
25
|
+
#include <sys/types.h>
|
26
|
+
#include "bool.h"
|
27
|
+
|
28
|
+
typedef void ( *external_callback_t )( void );
|
29
|
+
|
30
|
+
extern void ( *init_external_callback )( void );
|
31
|
+
extern void ( *finalize_external_callback )( void );
|
32
|
+
extern bool ( *push_external_callback )( external_callback_t callback );
|
33
|
+
extern void ( *run_external_callback )( void );
|
34
|
+
|
35
|
+
#define set_external_callback( callback ) push_external_callback( callback )
|
36
|
+
|
37
|
+
|
38
|
+
#endif // EXTERNAL_CALLBACK_H
|
39
|
+
|
40
|
+
|
41
|
+
/*
|
42
|
+
* Local variables:
|
43
|
+
* c-basic-offset: 2
|
44
|
+
* indent-tabs-mode: nil
|
45
|
+
* End:
|
46
|
+
*/
|
data/src/lib/messenger.c
CHANGED
@@ -141,6 +141,7 @@ enum {
|
|
141
141
|
MESSAGE_TYPE_NOTIFY,
|
142
142
|
MESSAGE_TYPE_REQUEST,
|
143
143
|
MESSAGE_TYPE_REPLY,
|
144
|
+
MESSAGE_TYPE_INVALID = 255,
|
144
145
|
};
|
145
146
|
|
146
147
|
typedef struct message_buffer {
|
@@ -172,6 +173,7 @@ typedef struct receive_queue {
|
|
172
173
|
struct sockaddr_un listen_addr;
|
173
174
|
dlist_element *client_sockets;
|
174
175
|
message_buffer *buffer;
|
176
|
+
bool in_progress;
|
175
177
|
} receive_queue;
|
176
178
|
|
177
179
|
typedef struct send_queue {
|
@@ -425,12 +427,14 @@ delete_receive_queue( void *service_name, void *_rq, void *user_data ) {
|
|
425
427
|
receive_queue_callback *cb;
|
426
428
|
|
427
429
|
assert( rq != NULL );
|
430
|
+
assert( rq->in_progress == false );
|
428
431
|
for ( element = rq->message_callbacks->next; element; element = element->next ) {
|
429
432
|
cb = element->data;
|
430
433
|
debug( "Deleting a callback ( function = %p, message_type = %#x ).", cb->function, cb->message_type );
|
431
434
|
xfree( cb );
|
432
435
|
}
|
433
436
|
delete_dlist( rq->message_callbacks );
|
437
|
+
rq->message_callbacks = NULL;
|
434
438
|
|
435
439
|
for ( element = rq->client_sockets->next; element; element = element->next ) {
|
436
440
|
client_socket = element->data;
|
@@ -591,6 +595,7 @@ create_receive_queue( const char *service_name ) {
|
|
591
595
|
rq->message_callbacks = create_dlist();
|
592
596
|
rq->client_sockets = create_dlist();
|
593
597
|
rq->buffer = create_message_buffer( messenger_recv_queue_length );
|
598
|
+
rq->in_progress = false;
|
594
599
|
|
595
600
|
insert_hash_entry( receive_queues, rq->service_name, rq );
|
596
601
|
|
@@ -699,11 +704,17 @@ delete_message_callback( const char *service_name, uint8_t message_type, void (
|
|
699
704
|
cb = e->data;
|
700
705
|
if ( ( cb->function == callback ) && ( cb->message_type == message_type ) ) {
|
701
706
|
debug( "Deleting a callback ( message_type = %#x, callback = %p ).", message_type, callback );
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
+
if ( rq->in_progress ) {
|
708
|
+
cb->function = NULL;
|
709
|
+
cb->message_type = MESSAGE_TYPE_INVALID;
|
710
|
+
}
|
711
|
+
else {
|
712
|
+
xfree( cb );
|
713
|
+
delete_dlist_element( e );
|
714
|
+
if ( rq->message_callbacks->next == NULL ) {
|
715
|
+
debug( "No more callback for message_type = %#x.", message_type );
|
716
|
+
delete_receive_queue( rq->service_name, rq, NULL );
|
717
|
+
}
|
707
718
|
}
|
708
719
|
return true;
|
709
720
|
}
|
@@ -844,17 +855,15 @@ send_queue_connect( send_queue *sq ) {
|
|
844
855
|
return -1;
|
845
856
|
}
|
846
857
|
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
return -1;
|
855
|
-
}
|
858
|
+
sq->socket_buffer_size = 1048576;
|
859
|
+
int ret = setsockopt( sq->server_socket, SOL_SOCKET, SO_SNDBUF, ( const void * ) &sq->socket_buffer_size, ( socklen_t ) sizeof( sq->socket_buffer_size ) );
|
860
|
+
if ( ret < 0 ) {
|
861
|
+
error( "Failed to set SO_SNDBUF to %d ( %s [%d] ).", sq->socket_buffer_size, strerror( errno ), errno );
|
862
|
+
close( sq->server_socket );
|
863
|
+
sq->server_socket = -1;
|
864
|
+
return -1;
|
856
865
|
}
|
857
|
-
|
866
|
+
ret = fcntl( sq->server_socket, F_SETFL, O_NONBLOCK );
|
858
867
|
if ( ret < 0 ) {
|
859
868
|
error( "Failed to set O_NONBLOCK ( %s [%d] ).", strerror( errno ), errno );
|
860
869
|
close( sq->server_socket );
|
@@ -873,7 +882,7 @@ send_queue_connect( send_queue *sq ) {
|
|
873
882
|
return 0;
|
874
883
|
}
|
875
884
|
|
876
|
-
set_fd_handler( sq->server_socket, on_send_read, sq,
|
885
|
+
set_fd_handler( sq->server_socket, on_send_read, sq, on_send_write, sq );
|
877
886
|
set_readable( sq->server_socket, true );
|
878
887
|
|
879
888
|
if ( sq->buffer != NULL && sq->buffer->data_length >= sizeof( message_header ) ) {
|
@@ -1092,9 +1101,7 @@ push_message_to_send_queue( const char *service_name, const uint8_t message_type
|
|
1092
1101
|
}
|
1093
1102
|
|
1094
1103
|
set_writable( sq->server_socket, true );
|
1095
|
-
|
1096
|
-
on_send_write( sq->server_socket, sq );
|
1097
|
-
}
|
1104
|
+
|
1098
1105
|
return true;
|
1099
1106
|
}
|
1100
1107
|
|
@@ -1215,7 +1222,7 @@ _clear_send_queue( const char *service_name ) {
|
|
1215
1222
|
return false;
|
1216
1223
|
}
|
1217
1224
|
|
1218
|
-
if ( sq->
|
1225
|
+
if ( sq->server_socket > -1 ) {
|
1219
1226
|
set_writable( sq->server_socket, false );
|
1220
1227
|
}
|
1221
1228
|
|
@@ -1369,14 +1376,13 @@ truncate_message_buffer( message_buffer *buf, size_t len ) {
|
|
1369
1376
|
len = buf->data_length;
|
1370
1377
|
}
|
1371
1378
|
|
1372
|
-
|
1373
|
-
|
1379
|
+
buf->data_length -= len;
|
1380
|
+
if ( buf->data_length == 0 ) {
|
1381
|
+
buf->head_offset = 0;
|
1374
1382
|
}
|
1375
1383
|
else {
|
1376
|
-
|
1377
|
-
buf->head_offset = 0;
|
1384
|
+
buf->head_offset += len;
|
1378
1385
|
}
|
1379
|
-
buf->data_length -= len;
|
1380
1386
|
}
|
1381
1387
|
|
1382
1388
|
|
@@ -1437,15 +1443,18 @@ static void
|
|
1437
1443
|
call_message_callbacks( receive_queue *rq, const uint8_t message_type, const uint16_t tag, void *data, size_t len ) {
|
1438
1444
|
assert( rq != NULL );
|
1439
1445
|
|
1440
|
-
dlist_element *element;
|
1446
|
+
dlist_element *element, *next;
|
1441
1447
|
receive_queue_callback *cb;
|
1442
1448
|
|
1443
1449
|
debug( "Calling message callbacks ( service_name = %s, message_type = %#x, tag = %#x, data = %p, len = %zu ).",
|
1444
1450
|
rq->service_name, message_type, tag, data, len );
|
1445
1451
|
|
1446
|
-
|
1452
|
+
assert( rq->in_progress != true );
|
1453
|
+
rq->in_progress = true;
|
1454
|
+
for ( element = rq->message_callbacks->next; element; element = next ) {
|
1455
|
+
next = element->next;
|
1447
1456
|
cb = element->data;
|
1448
|
-
if ( cb->message_type != message_type ) {
|
1457
|
+
if ( cb == NULL || cb->function == NULL || cb->message_type != message_type ) {
|
1449
1458
|
continue;
|
1450
1459
|
}
|
1451
1460
|
switch ( message_type ) {
|
@@ -1511,6 +1520,19 @@ call_message_callbacks( receive_queue *rq, const uint8_t message_type, const uin
|
|
1511
1520
|
assert( 0 );
|
1512
1521
|
}
|
1513
1522
|
}
|
1523
|
+
for ( element = rq->message_callbacks->next; element; element = next ) {
|
1524
|
+
next = element->next;
|
1525
|
+
cb = element->data;
|
1526
|
+
if ( cb->function == NULL ) {
|
1527
|
+
xfree( cb );
|
1528
|
+
delete_dlist_element( element );
|
1529
|
+
}
|
1530
|
+
}
|
1531
|
+
rq->in_progress = false;
|
1532
|
+
if ( rq->message_callbacks->next == NULL ) {
|
1533
|
+
debug( "No more callback for message_type = %#x.", message_type );
|
1534
|
+
delete_receive_queue( rq->service_name, rq, NULL );
|
1535
|
+
}
|
1514
1536
|
}
|
1515
1537
|
|
1516
1538
|
|
@@ -1648,11 +1670,6 @@ on_send_write( int fd, void *data ) {
|
|
1648
1670
|
debug( "Sending data to remote ( fd = %d, service_name = %s, buffer = %p, data_length = %zu ).",
|
1649
1671
|
fd, sq->service_name, get_message_buffer_head( sq->buffer ), sq->buffer->data_length );
|
1650
1672
|
|
1651
|
-
if ( sq->buffer->data_length < sizeof( message_header ) ) {
|
1652
|
-
set_writable( sq->server_socket, false );
|
1653
|
-
return;
|
1654
|
-
}
|
1655
|
-
|
1656
1673
|
void *send_data;
|
1657
1674
|
size_t send_len;
|
1658
1675
|
ssize_t sent_len;
|
@@ -1664,8 +1681,14 @@ on_send_write( int fd, void *data ) {
|
|
1664
1681
|
if ( sent_len == -1 ) {
|
1665
1682
|
int err = errno;
|
1666
1683
|
if ( err != EAGAIN && err != EWOULDBLOCK ) {
|
1667
|
-
|
1668
|
-
|
1684
|
+
if ( err == EPIPE ) {
|
1685
|
+
debug( "Failed to send ( service_name = %s, fd = %d, errno = %s [%d] ).",
|
1686
|
+
sq->service_name, fd, strerror( err ), err );
|
1687
|
+
}
|
1688
|
+
else {
|
1689
|
+
error( "Failed to send ( service_name = %s, fd = %d, errno = %s [%d] ).",
|
1690
|
+
sq->service_name, fd, strerror( err ), err );
|
1691
|
+
}
|
1669
1692
|
send_dump_message( MESSENGER_DUMP_SEND_CLOSED, sq->service_name, NULL, 0 );
|
1670
1693
|
|
1671
1694
|
set_readable( sq->server_socket, false );
|