static void send_eof_and_close(Channel * channel, int err) { ChannelNP * c = channel2np(channel); assert(c->magic == CHANNEL_MAGIC); if (channel->state == ChannelStateDisconnected) return; ibuf_flush(&c->ibuf); if (c->ibuf.handling_msg == HandleMsgTriggered) { /* Cancel pending message handling */ cancel_event(handle_channel_msg, c, 0); c->ibuf.handling_msg = HandleMsgIdle; } write_stream(&c->chan.out, MARKER_EOS); write_errno(&c->chan.out, err); write_stream(&c->chan.out, MARKER_EOM); np_flush_with_flags(c, 0); #if ENABLE_OutputQueue if (output_queue_is_empty(&c->out_queue)) #endif nopoll_conn_shutdown(c->np_socket); c->chan.state = ChannelStateDisconnected; np_post_read(&c->ibuf, c->ibuf.buf, c->ibuf.buf_size); notify_channel_closed(channel); if (channel->disconnected) { channel->disconnected(channel); } else { trace(LOG_PROTOCOL, "channel %#lx disconnected", c); if (channel->protocol != NULL) protocol_release(channel->protocol); } channel->protocol = NULL; }
static void proxy_disconnected(Channel * c) { Proxy * proxy = c->client_data; assert(c == proxy->c); assert(proxy->state == ProxyStateConnecting || proxy->state == ProxyStateConnected); proxy->state = ProxyStateDisconnected; if (proxy[proxy->other].state == ProxyStateDisconnected) { trace(LOG_PROXY, "Proxy disconnected"); if (proxy->other == -1) proxy--; assert(proxy[0].c->spg == proxy[1].c->spg); suspend_group_free(proxy[0].c->spg); proxy[0].c->spg = proxy[1].c->spg = NULL; proxy[0].c->client_data = proxy[1].c->client_data = NULL; protocol_release(proxy[0].proto); protocol_release(proxy[1].proto); loc_free(proxy); } else { channel_close(proxy[proxy->other].c); } }
void proxy_create(Channel * c1, Channel * c2) { TCFSuspendGroup * spg = suspend_group_alloc(); Proxy * proxy = loc_alloc_zero(2 * sizeof *proxy); int i; static int instance; assert(c1->hello_received); proxy[0].c = c1; proxy[0].proto = protocol_alloc(); proxy[0].other = 1; proxy[0].state = ProxyStateConnected; proxy[0].instance = instance; proxy[1].c = c2; proxy[1].proto = protocol_alloc(); proxy[1].other = -1; proxy[1].state = ProxyStateInitial; proxy[1].instance = instance++; trace(LOG_PROXY, "Proxy created, host services:"); for (i = 0; i < c1->peer_service_cnt; i++) { trace(LOG_PROXY, " %s", c1->peer_service_list[i]); protocol_get_service(proxy[1].proto, c1->peer_service_list[i]); } notify_channel_closed(c1); protocol_release(c1->client_data); c1->client_data = NULL; c1->hello_received = 1; c1->connecting = proxy_connecting; c1->connected = proxy_connected; c1->receive = proxy_receive; c1->disconnected = proxy_disconnected; c1->client_data = proxy; set_default_message_handler(proxy[0].proto, proxy_default_message_handler); c2->connecting = proxy_connecting; c2->connected = proxy_connected; c2->receive = proxy_receive; c2->disconnected = proxy_disconnected; c2->client_data = proxy + 1; set_default_message_handler(proxy[1].proto, proxy_default_message_handler); channel_set_suspend_group(c1, spg); channel_set_suspend_group(c2, spg); channel_start(c2); }
static int lua_protocol_gc(lua_State *L) { struct protocol_extra *pe = NULL; assert(L == luastate); if(lua_gettop(L) != 1 || (pe = lua2protocol(L, 1)) == NULL) { luaL_error(L, "wrong number or type of arguments"); } assert(pe->ucnt == 0); assert(pe->p != NULL); trace(LOG_LUA, "lua_protocol_gc %p", pe->p); protocol_release(pe->p); pe->p = NULL; return 0; }
static void channel_server_disconnected(Channel * c1) { trace(LOG_ALWAYS, "channel server disconnected"); protocol_release(c1->protocol); }