int swSSL_accept(swConnection *conn) { int n = SSL_do_handshake(conn->ssl); if (n == 1) { conn->ssl_state = SW_SSL_STATE_READY; if (conn->ssl->s3) { conn->ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; } return SW_READY; } long err = SSL_get_error(conn->ssl, n); if (err == SSL_ERROR_WANT_READ) { return SW_WAIT; } else if (err == SSL_ERROR_WANT_WRITE) { return SW_WAIT; } else if (err == SSL_ERROR_SSL) { swWarn("bad SSL client[%s:%d] .", swConnection_get_ip(conn), swConnection_get_port(conn)); return SW_ERROR; } else if (err == SSL_ERROR_SYSCALL) { swSysError("SSL error syscall."); return SW_ERROR; } swWarn("swSSL_accept() failed. Error: %s[%ld]", ERR_reason_error_string(err), err); return SW_ERROR; }
int my_onReceive(swFactory *factory, swEventData *req) { int ret; char resp_data[SW_BUFFER_SIZE]; swServer *serv = factory->ptr; swSendData resp; g_receive_count++; memcpy(&resp.info, &req->info, sizeof(resp.info)); printf("recv %d bytes, data=%s\n", req->info.len, req->data); int n = snprintf(resp_data, SW_BUFFER_SIZE, "Server: %*s", req->info.len, req->data); resp_data[n] = '\0'; resp.data = resp_data; resp.info.len = n; resp.info.type = SW_EVENT_TCP; resp.length = 0; printf("send %d bytes. data=%s\n", n, resp_data); return SW_OK; ret = factory->finish(factory, &resp); if (ret < 0) { printf("send to client fail. errno=%d\n", errno); } if (req->info.from_id >= serv->reactor_num) { struct in_addr addr; addr.s_addr = req->info.fd; //printf("onReceive[%d]: ip=%s:%d, Data=%s\n", g_receive_count, inet_ntoa(addr), req->info.from_id, rtrim(req->data, req->info.len)); } else { swConnection *conn = swWorker_get_connection(serv, req->info.fd); swoole_rtrim(req->data, req->info.len); printf("onReceive[%d]: ip=%s|port=%d Data=%s|Len=%d\n", g_receive_count, swConnection_get_ip(conn), swConnection_get_port(conn), req->data, req->info.len); } // req->info.type = 99; // factory->event(factory, g_controller_id, req); return SW_OK; }
int swSSL_accept(swConnection *conn) { int n = SSL_do_handshake(conn->ssl); if (n == 1) { conn->ssl_state = SW_SSL_STATE_READY; #if OPENSSL_VERSION_NUMBER < 0x10100000L #ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS if (conn->ssl->s3) { conn->ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; } #endif #endif return SW_READY; } long err = SSL_get_error(conn->ssl, n); if (err == SSL_ERROR_WANT_READ) { return SW_WAIT; } else if (err == SSL_ERROR_WANT_WRITE) { return SW_WAIT; } else if (err == SSL_ERROR_SSL) { swWarn("bad SSL client[%s:%d].", swConnection_get_ip(conn), swConnection_get_port(conn)); return SW_ERROR; } //EOF was observed else if (err == SSL_ERROR_SYSCALL && n == 0) { return SW_ERROR; } swWarn("swSSL_accept() failed. Error: %s[%ld]", ERR_reason_error_string(err), err); return SW_ERROR; }
/** * return the package total length */ int swProtocol_get_package_length(swProtocol *protocol, swConnection *conn, char *data, uint32_t size) { uint16_t length_offset = protocol->package_length_offset; int32_t body_length; /** * no have length field, wait more data */ if (size < length_offset + protocol->package_length_size) { return 0; } body_length = swoole_unpack(protocol->package_length_type, data + length_offset); //Length error //Protocol length is not legitimate, out of bounds or exceed the allocated length if (body_length < 0 || body_length > protocol->package_max_length) { swWarn("invalid package, remote_addr=%s:%d, length=%d, size=%d.", swConnection_get_ip(conn), swConnection_get_port(conn), body_length, size); return SW_ERR; } //total package length return protocol->package_body_offset + body_length; }
int swWebSocket_dispatch_frame(swConnection *conn, char *data, uint32_t length) { swString frame; bzero(&frame, sizeof(frame)); frame.str = data; frame.length = length; swString send_frame; bzero(&send_frame, sizeof(send_frame)); char buf[128]; send_frame.str = buf; send_frame.size = sizeof(buf); swWebSocket_frame ws; swWebSocket_decode(&ws, &frame); swString *frame_buffer; int frame_length; swListenPort *port; size_t offset; switch (ws.header.OPCODE) { case WEBSOCKET_OPCODE_CONTINUATION_FRAME: frame_buffer = conn->websocket_buffer; if (frame_buffer == NULL) { swWarn("bad frame[opcode=0]. remote_addr=%s:%d.", swConnection_get_ip(conn), swConnection_get_port(conn)); return SW_ERR; } offset = length - ws.payload_length; frame_length = length - offset; port = swServer_get_port(SwooleG.serv, conn->fd); //frame data overflow if (frame_buffer->length + frame_length > port->protocol.package_max_length) { swWarn("websocket frame is too big, remote_addr=%s:%d.", swConnection_get_ip(conn), swConnection_get_port(conn)); return SW_ERR; } //merge incomplete data swString_append_ptr(frame_buffer, data + offset, frame_length); //frame is finished, do dispatch if (ws.header.FIN) { swReactorThread_dispatch(conn, frame_buffer->str, frame_buffer->length); swString_free(frame_buffer); conn->websocket_buffer = NULL; } break; case WEBSOCKET_OPCODE_TEXT_FRAME: case WEBSOCKET_OPCODE_BINARY_FRAME: offset = length - ws.payload_length - 2; data[offset] = 1; data[offset + 1] = ws.header.OPCODE; if (!ws.header.FIN) { if (conn->websocket_buffer) { swWarn("merging incomplete frame, bad request. remote_addr=%s:%d.", swConnection_get_ip(conn), swConnection_get_port(conn)); return SW_ERR; } conn->websocket_buffer = swString_dup(data + offset, length - offset); } else { swReactorThread_dispatch(conn, data + offset, length - offset); } break; case WEBSOCKET_OPCODE_PING: if (length >= (sizeof(buf) - 2)) { swWarn("ping frame application data is too big. remote_addr=%s:%d.", swConnection_get_ip(conn), swConnection_get_port(conn)); return SW_ERR; } else if (length == 2) { swWebSocket_encode(&send_frame, NULL, 0, WEBSOCKET_OPCODE_PONG, 1, 0); } else { swWebSocket_encode(&send_frame, data += 2, length - 2, WEBSOCKET_OPCODE_PONG, 1, 0); } swConnection_send(conn, send_frame.str, send_frame.length, 0); break; case WEBSOCKET_OPCODE_PONG: break; case WEBSOCKET_OPCODE_CONNECTION_CLOSE: if (0x7d < (length - 2)) { return SW_ERR; } send_frame.str[0] = 0x88; send_frame.str[1] = 0x00; send_frame.length = 2; swConnection_send(conn, send_frame.str, 2, 0); return SW_ERR; default: swWarn("unknown opcode [%d].", ws.header.OPCODE); break; } return SW_OK; }
/** * @return SW_ERR: close the connection * @return SW_OK: continue */ int swProtocol_recv_check_length(swProtocol *protocol, swConnection *conn, swString *buffer) { int package_length; uint32_t recv_size; char swap[SW_BUFFER_SIZE]; do_recv: if (buffer->offset > 0) { recv_size = buffer->offset - buffer->length; } else { recv_size = protocol->package_length_offset + protocol->package_length_size; } int ret = swConnection_recv(conn, buffer->str + buffer->length, recv_size, 0); if (ret < 0) { switch (swConnection_error(errno)) { case SW_ERROR: swSysError("recv(%d, %d) failed.", conn->fd, recv_size); return SW_OK; case SW_CLOSE: conn->close_errno = errno; return SW_ERR; default: return SW_OK; } } else if (ret == 0) { return SW_ERR; } else { buffer->length += ret; if (conn->recv_wait) { if (buffer->length >= buffer->offset) { do_dispatch: ret = protocol->onPackage(conn, buffer->str, buffer->offset); conn->recv_wait = 0; int remaining_length = buffer->length - buffer->offset; if (remaining_length > 0) { assert(remaining_length < sizeof(swap)); memcpy(swap, buffer->str + buffer->offset, remaining_length); memcpy(buffer->str, swap, remaining_length); buffer->offset = 0; buffer->length = remaining_length; goto do_get_length; } else { swString_clear(buffer); return ret; } } else { return SW_OK; } } else { do_get_length: package_length = protocol->get_package_length(protocol, conn, buffer->str, buffer->length); //invalid package, close connection. if (package_length < 0) { return SW_ERR; } //no length else if (package_length == 0) { return SW_OK; } else if (package_length > protocol->package_max_length) { swWarn("package is too big, remote_addr=%s:%d, length=%d.", swConnection_get_ip(conn), swConnection_get_port(conn), package_length); return SW_ERR; } //get length success else { if (buffer->size < package_length) { if (swString_extend(buffer, package_length) < 0) { return SW_ERR; } } conn->recv_wait = 1; buffer->offset = package_length; if (buffer->length >= package_length) { goto do_dispatch; } else { goto do_recv; } } } } return SW_OK; }
/** * @return SW_ERR: close the connection * @return SW_OK: continue */ int swProtocol_recv_check_length(swProtocol *protocol, swConnection *conn, swString *buffer) { int package_length; uint8_t package_length_size = protocol->get_package_length_size ? protocol->get_package_length_size(conn) : protocol->package_length_size; uint32_t recv_size; if (conn->skip_recv) { conn->skip_recv = 0; goto do_get_length; } do_recv: if (conn->active == 0) { return SW_OK; } if (buffer->offset > 0) { recv_size = buffer->offset - buffer->length; } else { recv_size = protocol->package_length_offset + package_length_size; } int n = swConnection_recv(conn, buffer->str + buffer->length, recv_size, 0); if (n < 0) { switch (swConnection_error(errno)) { case SW_ERROR: swSysError("recv(%d, %d) failed.", conn->fd, recv_size); return SW_OK; case SW_CLOSE: conn->close_errno = errno; return SW_ERR; default: return SW_OK; } } else if (n == 0) { return SW_ERR; } else { buffer->length += n; if (conn->recv_wait) { if (buffer->length >= buffer->offset) { do_dispatch: if (protocol->onPackage(conn, buffer->str, buffer->offset) < 0) { return SW_ERR; } if (conn->removed) { return SW_OK; } conn->recv_wait = 0; int remaining_length = buffer->length - buffer->offset; if (remaining_length > 0) { memmove(buffer->str, buffer->str + buffer->offset, remaining_length); buffer->offset = 0; buffer->length = remaining_length; goto do_get_length; } else { swString_clear(buffer); #ifdef SW_USE_OPENSSL if (conn->ssl) { goto do_recv; } #endif } } return SW_OK; } else { do_get_length: package_length = protocol->get_package_length(protocol, conn, buffer->str, buffer->length); //invalid package, close connection. if (package_length < 0) { return SW_ERR; } //no length else if (package_length == 0) { return SW_OK; } else if (package_length > protocol->package_max_length) { swWarn("package is too big, remote_addr=%s:%d, length=%d.", swConnection_get_ip(conn), swConnection_get_port(conn), package_length); return SW_ERR; } //get length success else { if (buffer->size < package_length) { if (swString_extend(buffer, package_length) < 0) { return SW_ERR; } } conn->recv_wait = 1; buffer->offset = package_length; if (buffer->length >= package_length) { goto do_dispatch; } else { goto do_recv; } } } } return SW_OK; }
/** * @return SW_ERR: close the connection * @return SW_OK: continue */ int swProtocol_recv_check_length(swProtocol *protocol, swConnection *conn, swString *buffer) { char *recvbuf; int ret; uint32_t recvbuf_size; do_recv: recvbuf = buffer->str + buffer->length; recvbuf_size = buffer->offset > 0 ? buffer->offset - buffer->length : protocol->package_length_offset + protocol->package_length_size; int n = swConnection_recv(conn, recvbuf, recvbuf_size, 0); if (n < 0) { switch (swConnection_error(errno)) { case SW_ERROR: swSysError("recv(%d, %p, %d) failed.", conn->fd, recvbuf, recvbuf_size); return SW_OK; case SW_CLOSE: return SW_ERR; default: return SW_OK; } } else if (n == 0) { return SW_ERR; } else { buffer->length += n; if (conn->recv_wait) { if (buffer->length == buffer->offset) { do_package: ret = protocol->onPackage(conn, buffer->str, buffer->length); conn->recv_wait = 0; swString_clear(buffer); return ret; } else { return SW_OK; } } else { int package_length = protocol->get_package_length(protocol, conn, buffer->str, buffer->length); //invalid package, close connection. if (package_length < 0) { return SW_ERR; } //no length else if (package_length == 0) { return SW_OK; } else if (package_length > protocol->package_max_length) { swWarn("package is too big, remote_addr=%s:%d, length=%d.", swConnection_get_ip(conn), swConnection_get_port(conn), package_length); return SW_ERR; } //get length success else { if (buffer->size < package_length) { if (swString_extend(buffer, package_length) < 0) { return SW_ERR; } } conn->recv_wait = 1; buffer->offset = package_length; if (buffer->length == package_length) { goto do_package; } else { goto do_recv; } } } } return SW_OK; }