@@ -72,6 +72,9 @@ NS_INTERNAL struct ns_connection *ns_finish_connect(struct ns_connection *nc,
72
72
NS_INTERNAL int ns_parse_address (const char * str , union socket_address * sa ,
73
73
int * proto , char * host , size_t host_len );
74
74
NS_INTERNAL void ns_call (struct ns_connection * , int ev , void * ev_data );
75
+ NS_INTERNAL void ns_forward (struct ns_connection * , struct ns_connection * );
76
+ NS_INTERNAL void ns_add_conn (struct ns_mgr * mgr , struct ns_connection * c );
77
+ NS_INTERNAL void ns_remove_conn (struct ns_connection * c );
75
78
76
79
#ifndef NS_DISABLE_FILESYSTEM
77
80
NS_INTERNAL int find_index_file (char * , size_t , const char * , ns_stat_t * );
@@ -1649,15 +1652,16 @@ static void ns_ev_mgr_free(struct ns_mgr *mgr);
1649
1652
static void ns_ev_mgr_add_conn (struct ns_connection * nc );
1650
1653
static void ns_ev_mgr_remove_conn (struct ns_connection * nc );
1651
1654
1652
- static void ns_add_conn (struct ns_mgr * mgr , struct ns_connection * c ) {
1655
+ NS_INTERNAL void ns_add_conn (struct ns_mgr * mgr , struct ns_connection * c ) {
1656
+ c -> mgr = mgr ;
1653
1657
c -> next = mgr -> active_connections ;
1654
1658
mgr -> active_connections = c ;
1655
1659
c -> prev = NULL ;
1656
1660
if (c -> next != NULL ) c -> next -> prev = c ;
1657
1661
ns_ev_mgr_add_conn (c );
1658
1662
}
1659
1663
1660
- static void ns_remove_conn (struct ns_connection * conn ) {
1664
+ NS_INTERNAL void ns_remove_conn (struct ns_connection * conn ) {
1661
1665
if (conn -> prev == NULL ) conn -> mgr -> active_connections = conn -> next ;
1662
1666
if (conn -> prev ) conn -> prev -> next = conn -> next ;
1663
1667
if (conn -> next ) conn -> next -> prev = conn -> prev ;
@@ -3063,6 +3067,118 @@ int ns_check_ip_acl(const char *acl, uint32_t remote_ip) {
3063
3067
3064
3068
return allowed == '+' ;
3065
3069
}
3070
+
3071
+ /* Move data from one connection to another */
3072
+ void ns_forward (struct ns_connection * from , struct ns_connection * to ) {
3073
+ ns_send (to , from -> recv_mbuf .buf , from -> recv_mbuf .len );
3074
+ mbuf_remove (& from -> recv_mbuf , from -> recv_mbuf .len );
3075
+ }
3076
+ #ifdef NS_MODULE_LINES
3077
+ #line 1 "src/multithreading.c"
3078
+ /**/
3079
+ #endif
3080
+ /*
3081
+ * Copyright (c) 2014 Cesanta Software Limited
3082
+ * All rights reserved
3083
+ */
3084
+
3085
+ /* Amalgamated: #include "internal.h" */
3086
+
3087
+ #ifdef NS_ENABLE_THREADS
3088
+
3089
+ static void multithreaded_ev_handler (struct ns_connection * c , int ev , void * p );
3090
+
3091
+ /*
3092
+ * This thread function executes user event handler.
3093
+ * It runs an event manager that has only one connection, until that
3094
+ * connection is alive.
3095
+ */
3096
+ static void * per_connection_thread_function (void * param ) {
3097
+ struct ns_connection * c = (struct ns_connection * ) param ;
3098
+ struct ns_mgr m ;
3099
+
3100
+ ns_mgr_init (& m , NULL );
3101
+ ns_add_conn (& m , c );
3102
+ while (m .active_connections != NULL ) {
3103
+ ns_mgr_poll (& m , 1000 );
3104
+ }
3105
+ ns_mgr_free (& m );
3106
+
3107
+ return param ;
3108
+ }
3109
+
3110
+ static void link_conns (struct ns_connection * c1 , struct ns_connection * c2 ) {
3111
+ c1 -> priv_2 = c2 ;
3112
+ c2 -> priv_2 = c1 ;
3113
+ }
3114
+
3115
+ static void unlink_conns (struct ns_connection * c ) {
3116
+ struct ns_connection * peer = (struct ns_connection * ) c -> priv_2 ;
3117
+ if (peer != NULL ) {
3118
+ peer -> flags |= NSF_SEND_AND_CLOSE ;
3119
+ peer -> priv_2 = NULL ;
3120
+ }
3121
+ c -> priv_2 = NULL ;
3122
+ }
3123
+
3124
+ static void forwarder_ev_handler (struct ns_connection * c , int ev , void * p ) {
3125
+ (void ) p ;
3126
+ if (ev == NS_RECV && c -> priv_2 ) {
3127
+ ns_forward (c , c -> priv_2 );
3128
+ } else if (ev == NS_CLOSE ) {
3129
+ unlink_conns (c );
3130
+ }
3131
+ }
3132
+
3133
+ static void spawn_handling_thread (struct ns_connection * nc ) {
3134
+ struct ns_mgr dummy = {};
3135
+ sock_t sp [2 ];
3136
+ struct ns_connection * c [2 ];
3137
+
3138
+ /*
3139
+ * Create a socket pair, and wrap each socket into the connection with
3140
+ * dummy event manager.
3141
+ * c[0] stays in this thread, c[1] goes to another thread.
3142
+ */
3143
+ ns_socketpair (sp , SOCK_STREAM );
3144
+ c [0 ] = ns_add_sock (& dummy , sp [0 ], forwarder_ev_handler );
3145
+ c [1 ] = ns_add_sock (& dummy , sp [1 ], nc -> listener -> priv_1 );
3146
+
3147
+ /* Interlink client connection with c[0] */
3148
+ link_conns (c [0 ], nc );
3149
+
3150
+ /*
3151
+ * Switch c[0] manager from the dummy one to the real one. c[1] manager
3152
+ * will be set in another thread, allocated on stack of that thread.
3153
+ */
3154
+ ns_add_conn (nc -> mgr , c [0 ]);
3155
+
3156
+ /*
3157
+ * Dress c[1] as nc.
3158
+ * TODO(lsm): code in accept_conn() looks similar. Refactor.
3159
+ */
3160
+ c [1 ]-> listener = nc -> listener ;
3161
+ c [1 ]-> proto_handler = nc -> proto_handler ;
3162
+ c [1 ]-> proto_data = nc -> proto_data ;
3163
+ c [1 ]-> user_data = nc -> user_data ;
3164
+
3165
+ ns_start_thread (per_connection_thread_function , c [1 ]);
3166
+ }
3167
+
3168
+ static void multithreaded_ev_handler (struct ns_connection * c , int ev , void * p ) {
3169
+ (void ) p ;
3170
+ if (ev == NS_ACCEPT ) {
3171
+ spawn_handling_thread (c );
3172
+ c -> handler = forwarder_ev_handler ;
3173
+ }
3174
+ }
3175
+
3176
+ void ns_enable_multithreading (struct ns_connection * nc ) {
3177
+ /* Wrap user event handler into our multithreaded_ev_handler */
3178
+ nc -> priv_1 = nc -> handler ;
3179
+ nc -> handler = multithreaded_ev_handler ;
3180
+ }
3181
+ #endif
3066
3182
#ifdef NS_MODULE_LINES
3067
3183
#line 1 "src/http.c"
3068
3184
/**/
@@ -3625,12 +3741,6 @@ static void free_http_proto_data(struct ns_connection *nc) {
3625
3741
}
3626
3742
}
3627
3743
3628
- /* Move data from one connection to another */
3629
- static void ns_forward (struct ns_connection * from , struct ns_connection * to ) {
3630
- ns_send (to , from -> recv_mbuf .buf , from -> recv_mbuf .len );
3631
- mbuf_remove (& from -> recv_mbuf , from -> recv_mbuf .len );
3632
- }
3633
-
3634
3744
static void transfer_file_data (struct ns_connection * nc ) {
3635
3745
struct proto_data_http * dp = (struct proto_data_http * ) nc -> proto_data ;
3636
3746
char buf [NS_MAX_HTTP_SEND_IOBUF ];
@@ -5833,8 +5943,7 @@ void ns_hexdump_connection(struct ns_connection *nc, const char *path,
5833
5943
if ((fp = fopen (path , "a" )) != NULL ) {
5834
5944
ns_sock_to_str (nc -> sock , src , sizeof (src ), 3 );
5835
5945
ns_sock_to_str (nc -> sock , dst , sizeof (dst ), 7 );
5836
- fprintf (fp , "%lu %p %s %s %s %d\n" , (unsigned long ) time (NULL ),
5837
- nc -> user_data , src ,
5946
+ fprintf (fp , "%lu %p %s %s %s %d\n" , (unsigned long ) time (NULL ), nc , src ,
5838
5947
ev == NS_RECV ? "<-" : ev == NS_SEND ? "->" : ev == NS_ACCEPT
5839
5948
? "<A"
5840
5949
: ev == NS_CONNECT
0 commit comments