static int _cb(struct skynet_context * ctx, void * ud, int type, int session, uint32_t source, const void * msg, size_t sz) { struct gate *g = ud; switch(type) { case PTYPE_TEXT: _ctrl(g , msg , (int)sz); break; case PTYPE_CLIENT: { if (sz <=4 ) { skynet_error(ctx, "Invalid client message from %x",source); break; } // The last 4 bytes in msg are the id of socket, write following bytes to it const uint8_t * idbuf = msg + sz - 4; uint32_t uid = idbuf[0] | idbuf[1] << 8 | idbuf[2] << 16 | idbuf[3] << 24; int id = hashid_lookup(&g->hash, uid); if (id>=0) { // don't send id (last 4 bytes) skynet_socket_send(ctx, uid, (void*)msg, sz-4); // return 1 means don't free msg return 1; } else { skynet_error(ctx, "Invalid client id %d from %x",(int)uid,source); break; } } case PTYPE_SOCKET: // recv socket message from skynet_socket dispatch_socket_message(g, msg, (int)(sz-sizeof(struct skynet_socket_message))); break; } return 0; }
static int _cb(struct skynet_context * ctx, void * ud, int type, int session, uint32_t source, const void * msg, size_t sz) { struct gate *g = ud; if (type == PTYPE_TEXT) { _ctrl(ctx, g , msg , (int)sz); return 0; } assert(type == PTYPE_RESPONSE); struct mread_pool * m = g->pool; int connection_id = mread_poll(m,100); // timeout : 100ms if (connection_id < 0) { skynet_command(ctx, "TIMEOUT", "1"); } else { int id = g->map[connection_id].uid; if (id == 0) { id = _gen_id(g, connection_id); int fd = mread_socket(m , connection_id); struct sockaddr_in remote_addr; socklen_t len = sizeof(struct sockaddr_in); getpeername(fd, (struct sockaddr *)&remote_addr, &len); _report(g, ctx, "%d open %d %s:%u",id,fd,inet_ntoa(remote_addr.sin_addr),ntohs(remote_addr.sin_port)); } uint8_t * plen = mread_pull(m,g->header_size); if (plen == NULL) { if (mread_closed(m)) { _remove_id(g,id); _report(g, ctx, "%d close", id); } goto _break; } // big-endian int len ; if (g->header_size == 2) { len = plen[0] << 8 | plen[1]; } else { len = plen[0] << 24 | plen[1] << 16 | plen[2] << 8 | plen[3]; } void * data = mread_pull(m, len); if (data == NULL) { if (mread_closed(m)) { _remove_id(g,id); _report(g, ctx, "%d close", id); } goto _break; } _forward(ctx, g, id, data, len); mread_yield(m); _break: skynet_command(ctx, "TIMEOUT", "0"); } return 0; }