int mongrel2_ws_reply(mongrel2_socket *pub_socket, mongrel2_request *req, bstring data){ size_t req_len = blength(data); uint8_t *req_data = (uint8_t*)bdata(data); size_t payload_len = 0; uint8_t *payload_data = NULL; // Simplest code but seems to be unsafe with chrome 14? int retval = mongrel2_ws_frame_create(0,req_len,&payload_len,&payload_data); if(retval != 0){ fprintf(stderr,"mongrel2_ws_reply failed with errno %d\n",retval); return -1; } mongrel2_ws_frame_set_payload(payload_len,payload_data,req_len,req_data); mongrel2_ws_frame_set_opcode(payload_len,payload_data,OP_TEXT); mongrel2_ws_frame_set_fin(payload_len,payload_data); // Instead, let's chunk it to a bunch of small messages // int fullchunks = req_len % WEBSOCKET_SMALL_MAX; // int leftoverbytes = req_len / WEBSOCKET_SMALL_MAX; // bstring chunk; // for(int i=0; i<fullchunks; i++){ // uint8_t chunk_payload[WEBSOCKET_SMALL_MAX]; // chunk = bmidstr(data,i*WEBSOCKET_SMALL_MAX,i*WEBSOCKET_SMALL_MAX+WEBSOCKET_SMALL_MAX-1); // fullchunks--; // } #ifndef NDEBUG mongrel2_ws_frame_debug(payload_len,payload_data); #endif bstring outgoing = blk2bstr(payload_data,payload_len); assert(blength(outgoing) == payload_len); mongrel2_reply(pub_socket,req,outgoing); free(payload_data); bdestroy(outgoing); return 0; }
int main(int argc, char **args){ signal(SIGINT,&call_for_stop); if(argc != 3){ fprintf(stderr,"%s RECV SEND\n",args[0]); exit(1); } bstring pull_addr = bfromcstr(args[1]); bstring pub_addr = bfromcstr(args[2]); mongrel2_ctx *ctx = mongrel2_init(1); mongrel2_socket *pull_socket = mongrel2_pull_socket(ctx); mongrel2_connect(pull_socket, bdata(pull_addr)); mongrel2_socket *pub_socket = mongrel2_pub_socket(ctx); mongrel2_connect(pub_socket, bdata(pub_addr)); mongrel2_set_identity(pub_socket, bdata(&SENDER) ); // Polling is done to show how to do a clean shutdown int poll_response; zmq_pollitem_t socket_tracker; socket_tracker.socket = pull_socket->zmq_socket; socket_tracker.events = ZMQ_POLLIN; // Let's try out some C-style ADT goodness m2_ws_sessions_state sessions; mongrel2_ws_sessions_state_init(&sessions); mongrel2_ws_sessions_state_unlock(&sessions); mongrel2_request *request = NULL; while(shutdown != 1){ poll_response = zmq_poll(&socket_tracker,1,500*1000); if(poll_response > 0){ request = mongrel2_recv(pull_socket); if(request != NULL && mongrel2_request_for_disconnect(request) != 1){ if(mongrel2_ws_sessions_state_contains(&sessions,request)){ printf("We had it already\n"); } else { mongrel2_ws_reply_upgrade(request,pub_socket); mongrel2_ws_sessions_state_add(&sessions,request); } if(blength(request->body) > 0){ // mongrel2_ws_frame_debug(blength(request->body),(uint8_t*)bdata(request->body)); if(OP_CLOSE == mongrel2_ws_frame_get_opcode(blength(request->body), (uint8_t*)bdata(request->body))){ printf("Hey, it's a close\n"); } else { printf("Not a OP_CLOSE. bstring length: '%d'\n",blength(request->body)); #ifndef NDEBUG mongrel2_ws_frame_debug(blength(request->body), (uint8_t*)bdata(request->body)); #endif } } else { // mongrel2_ws_reply(pub_socket,request,(const bstring)&HELLO); mongrel2_ws_broadcast(pub_socket,&sessions,(const bstring)&HELLO); } } else { fprintf(stdout,"Connection %d disconnected\n", request->conn_id); mongrel2_ws_sessions_state_remove(&sessions,request); mongrel2_disconnect(pub_socket,request); } } else if(poll_response < 0) { printf("ZMQ poller had an error"); } } printf("\nThanks for playing\n"); return 0; }