/* Forwards FM Packets to Shared Transport */ int fm_st_send(struct sk_buff *skb) { long len; FMDRV_API_START(); if (skb == NULL) { FM_DRV_ERR("Invalid skb, can't send"); FMDRV_API_EXIT(-ENOMEM); return -ENOMEM; } /* Is anyone called without claiming FM ST? */ if (is_fm_st_claimed == FM_ST_CLAIMED ) { /* Forward FM packet(SKB) to ST for the transmission */ len = st_write(skb); if (len < 0) { /* Something went wrong in st write , free skb memory */ kfree_skb(skb); FM_DRV_ERR(" ST write failed (%ld)", len); FMDRV_API_EXIT(-EAGAIN); return -EAGAIN; } } else { /* Nobody calimed FM ST */ kfree_skb(skb); FM_DRV_ERR("FM ST is not claimed, Can't send skb"); FMDRV_API_EXIT(-EAGAIN); return -EAGAIN; } FMDRV_API_EXIT(0); return 0; }
// read/write with call multiplexing void task8(void* arg) { static st_netfd_t rfd0 = st_open("/dev/random", O_RDONLY, S_IRUSR); static st_netfd_t rfd1 = st_open("/dev/urandom", O_RDONLY, S_IRUSR); static st_netfd_t rfd2 = st_open("/dev/zero", O_RDONLY, S_IRUSR); static st_netfd_t wfd = st_open("/dev/null", O_WRONLY, S_IWUSR); int rc = 0; static const int count = 10000; for (long i = 0; i < count; ++i) { if ((rc = st_read(rfd0, &rc, sizeof(rc), -1)) <= 0) { std::cout << "st_read " << rc << " " << strerror(rc) << std::endl; exit(1); } if ((rc = st_read(rfd1, &rc, sizeof(rc), -1)) <= 0) { std::cout << "st_read " << rc << " " << strerror(rc) << std::endl; exit(1); } if ((rc = st_read(rfd2, &rc, sizeof(rc), -1)) <= 0) { std::cout << "st_read " << rc << " " << strerror(rc) << std::endl; exit(1); } if ((rc = st_write(wfd, &rc, sizeof(rc), -1)) <= 0) { std::cout << "st_write " << rc << " " << strerror(rc) << std::endl; exit(1); } } }
_st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen, st_utime_t timeout) { int osfd, err; _st_netfd_t *newfd; _st_netfd_t **p = (_st_netfd_t **) fd->aux_data; ssize_t n; char c; for ( ; ; ) { if (p == NULL) { osfd = accept(fd->osfd, addr, (socklen_t *)addrlen); } else { /* Get the lock */ n = st_read(p[0], &c, 1, timeout); if (n < 0) { return NULL; } ST_ASSERT(n == 1); /* Got the lock */ osfd = accept(fd->osfd, addr, (socklen_t *)addrlen); /* Unlock */ err = errno; n = st_write(p[1], &c, 1, timeout); ST_ASSERT(n == 1); errno = err; } if (osfd >= 0) { break; } if (errno == EINTR) { continue; } if (!_IO_NOT_READY_ERROR) { return NULL; } /* Wait until the socket becomes readable */ if (st_netfd_poll(fd, POLLIN, timeout) < 0) { return NULL; } } /* On some platforms the new socket created by accept() inherits */ /* the nonblocking attribute of the listening socket */ #if defined (MD_ACCEPT_NB_INHERITED) newfd = _st_netfd_new(osfd, 0, 1); #elif defined (MD_ACCEPT_NB_NOT_INHERITED) newfd = _st_netfd_new(osfd, 1, 1); #else #error Unknown OS #endif if (!newfd) { err = errno; close(osfd); errno = err; } return newfd; }
int _peer_connect(const peer_index_t index) { int client_fd, rv, result; struct addrinfo hints, *ai, *p; struct peer_info *peer_info; result = 0; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; peer_info = &peer_list[index]; LOG("[%d] 向 Peer #%d %s:%s 建立互联\n", self_index, index, peer_info->host, peer_info->port); if ((rv = getaddrinfo(peer_info->host, peer_info->port, &hints, &ai)) != 0) { ERR("[%d] failed to getaddrinfo to peer #%d\n", self_index, index); return -1; } for (p = ai; p != NULL; p = p->ai_next) { if ((client_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { continue; } if ((peer_info->rpc_fd = st_netfd_open_socket(client_fd)) == NULL) { close(client_fd); continue; } if ((rv = st_connect(peer_info->rpc_fd, p->ai_addr, p->ai_addrlen, ST_UTIME_NO_TIMEOUT)) != 0) { st_netfd_close(peer_info->rpc_fd); continue; } // 写入 1 字节的 rpc 握手头 if ((rv = st_write(peer_info->rpc_fd, (char *)&self_index, 1, ST_UTIME_NO_TIMEOUT)) == -1) { ERR("[%d] handshake failed.\n", self_index); result = -1; } break; } if (p == NULL) { ERR("[%d] failed to connect to peer #%d.\n", self_index, index); result = -1; } freeaddrinfo(ai); ai = NULL; p = NULL; return result; }
bool_t check_string_write(void) { stringer_t *output = MANAGEDBUF(1024), *strings[3] = { MANAGEDBUF(32), MANAGEDBUF(64), MANAGEDBUF(128) }; for (int i = 0; i < 3; i++) { rand_write(strings[i]); } if (st_write(NULL, strings[0], strings[1], strings[2]) != 224) { return false; } if (st_write(output, strings[0], strings[1], strings[2]) != 224) { return false; } return true; }
stringer_t * org_signet_get(prime_org_signet_t *org, stringer_t *output) { size_t length; int_t written = 0; stringer_t *result = NULL; if (!org || !(length = org_signet_length(org))) { log_pedantic("An invalid org signet was supplied for serialization."); return NULL; } // See if we have a valid output buffer, or if output is NULL, allocate a buffer to hold the output. else if (output && (!st_valid_destination(st_opt_get(output)) || st_avail_get(output) < length)) { log_pedantic("An output string was supplied but it does not represent a buffer capable of holding the output."); return NULL; } else if (!output && !(result = st_alloc(length))) { log_pedantic("Could not allocate a buffer large enough to hold encoded result. { requested = %zu }", length); return NULL; } else if (!output) { output = result; } st_wipe(output); // Calculate the size, by writing out all the fields (minus the header) using a NULL output. length = st_write(NULL, prime_field_write(PRIME_ORG_SIGNET, 1, ED25519_KEY_PUB_LEN, ed25519_public_get(org->signing, MANAGEDBUF(32)), MANAGEDBUF(34)), prime_field_write(PRIME_ORG_SIGNET, 3, SECP256K1_KEY_PUB_LEN, secp256k1_public_get(org->encryption, MANAGEDBUF(33)), MANAGEDBUF(35)), prime_field_write(PRIME_ORG_SIGNET, 4, ED25519_SIGNATURE_LEN, org->signature, MANAGEDBUF(65))); // Then output them again into the actual output buffer, but this time include the header. This is very primitive serialization logic. if ((written = st_write(output, prime_header_org_signet_write(length, MANAGEDBUF(5)), prime_field_write(PRIME_ORG_SIGNET, 1, ED25519_KEY_PUB_LEN, ed25519_public_get(org->signing, MANAGEDBUF(32)), MANAGEDBUF(34)), prime_field_write(PRIME_ORG_SIGNET, 3, SECP256K1_KEY_PUB_LEN, secp256k1_public_get(org->encryption, MANAGEDBUF(33)), MANAGEDBUF(35)), prime_field_write(PRIME_ORG_SIGNET, 4, ED25519_SIGNATURE_LEN, org->signature, MANAGEDBUF(65)))) != (length + 5)) { log_pedantic("The organizational signet didn't serialize to the expected length. { written = %i }", written); st_cleanup(result); return NULL; } return output; }
/** * @brief Derive an organizational signet from the corresponding private key structures. */ prime_org_signet_t * org_signet_generate(prime_org_key_t *org) { prime_org_signet_t *signet = NULL; stringer_t *signing = NULL, *encryption = NULL, *cryptographic = MANAGEDBUF(69); // Ensure the org structure contains the necessary private keys. if (!org || !org->encryption || !org->signing || org->signing->type != ED25519_PRIV) { return NULL; } else if (!(signet = mm_alloc(sizeof(prime_org_signet_t)))) { return NULL; } // Store the public singing, and encryption keys. else if (!(signing = ed25519_public_get(org->signing, NULL)) || !(encryption = secp256k1_public_get(org->encryption, NULL))) { log_pedantic("PRIME organizational signet generation failed, the public keys could not be derived from the provided private keys."); org_signet_free(signet); st_cleanup(signing); return NULL; } // Generate a serialized signet with the cryptographic fields. else if (st_write(cryptographic, prime_field_write(PRIME_ORG_SIGNET, 1, ED25519_KEY_PUB_LEN, signing, MANAGEDBUF(34)), prime_field_write(PRIME_ORG_SIGNET, 3, SECP256K1_KEY_PUB_LEN, encryption, MANAGEDBUF(35))) != 69) { log_pedantic("PRIME organizational signet generation failed, the serialized cryptographic signet could not be derived."); org_signet_free(signet); st_free(encryption); st_free(signing); return NULL; } // Generate a signature using the serialized cryptographic fields. else if (!(signet->signature = ed25519_sign(org->signing, cryptographic, NULL))) { log_pedantic("PRIME organizational signet generation failed, the cryptographic signet signature could not be derived."); org_signet_free(signet); st_free(encryption); st_free(signing); return NULL; } // Finally, convert the serialized public keys into usable structures. else if (!(signet->signing = ed25519_public_set(signing)) || !(signet->encryption = secp256k1_public_set(encryption))) { log_pedantic("PRIME organizational signet generation failed, the serialized public keys could not be parsed."); org_signet_free(signet); st_free(encryption); st_free(signing); return NULL; } // We no longer need the serialized public keys. st_free(encryption); st_free(signing); return signet; }
int peer_request(const char *peer_name, const char *method, const char *parameter) { static uint8_t request_id = 0; LOG("[%d] 准备发出一次 RPC 请求,目标结点:%s,方法:%s,参数:%s\n", self_index, peer_name, method, parameter); peer_index_t dest_index; struct peer_info *peer_info; int i, len, matched; for (dest_index = 0; dest_index < peer_count; dest_index ++) { if (dest_index != self_index) { peer_info = &peer_list[dest_index]; len = strlen(peer_info->name); matched = 1; for (i = 0; i < len; i++) { if (peer_info->name[i] != peer_name[i]) { matched = 0; break; } } if (matched == 0) continue; // 匹配到结点对应的 dest_index,构造 RPC 业务包并准备发送 struct rpc_package_head *head; char *data; head = protocol_package_create(REQUEST, self_index, dest_index, request_id++, method, parameter); rpcpkg_len pkg_len, cursor; data = protocol_encode(head, &cursor); // 释放结构体 protocol_package_free(head); head = NULL; // 发送缓冲区包内容 if ((pkg_len = st_write(peer_info->rpc_fd, data, cursor, ST_UTIME_NO_TIMEOUT)) != cursor) { ERR("[%d] 写入 RPC 包长度 %d 与原包长 %d 不符,错误信息:%s\n", self_index, pkg_len, cursor, strerror(errno)); } free(data); data = NULL; return cursor; } } return 0; }
// read/write without call multiplexing void task7(void* arg) { static st_netfd_t wfd = st_open("/dev/null", O_WRONLY, S_IWUSR); int rc = 0; static const int count = 40000; for (long i = 0; i < count; ++i) { if ((rc = st_write(wfd, &rc, sizeof(rc), -1)) <= 0) { std::cout << "st_write " << rc << " " << strerror(rc) << std::endl; exit(1); } } }
bool SMUSync::PacketWebService(st_netfd_t fd, const char* status_code, const std::vector<SyncPlatformDataResult>& result) { std::string body; std::string head; std::string msg; { if(result.size() != 0) { DMXml xml; xml.NewRoot("SyncResponseResult"); for(int i =0;i<result.size();i++) { xml.NewChild("SyncResult",0)->NewChild("StreamNo",result[i].SerialNumber.c_str())->GetParent() ->NewChild("Result", result[i].ErrCode.c_str())->GetParent() ->NewChild("Descr", result[i].Desc.c_str())->GetParent() ->NewChild("OPFlag",result[i].UserState.c_str())->GetParent() ->NewChild("ViewerName",result[i].ViewName.c_str())->GetParent(); xml.GetParent(); } body = xml.Encode(); } else { body = "<body>This is HMSyncPlatformServer, Is Running!</body>"; } } char body_len[10] = {}; sprintf_s(body_len, " %d\r\n",body.length()); head = "HTTP/1.1 "; head.append(status_code); head.append("\r\n"); head.append("Server: HMSyncPlatformServer\r\n"); head.append("Content-Type: text/html\r\n"); head.append("Accept-Ranges: byte\r\n"); head.append("Connection: close\r\n"); head.append("Content-Length: "); head.append(body_len); head.append("\r\n"); msg.append(head); msg.append(body); st_write(fd, msg.c_str(), msg.length()+1, -1); return true; }
/**************************************************************************** * Function - st_wdt_write_test * Functionality - This function recieves the test params and calls * the write * Input Params - info,test_id * Return Value - 0: SUCCESS, -1: FAILURE * Note - None ****************************************************************************/ int st_wdt_write_test(struct st_wdt_testparams *info, char *test_id, int fileDesc) { int result = SUCCESS; int retVal = 0; do { retVal = st_write(fileDesc, "C\0", ST_WDT_WRITEBUFF_LEN); if (FAILURE == retVal) { TEST_PRINT_ERR("file write failed "); result = FAILURE; } } while (0); return result; }
stringer_t * org_signet_fingerprint(prime_org_signet_t *org, stringer_t *output) { stringer_t *holder = MANAGEDBUF(134); if (!org || !org->signing || !org->encryption || !org->signature || st_length_get(org->signature) != 64) { return false; } else if (st_write(holder, prime_field_write(PRIME_ORG_SIGNET, 1, ED25519_KEY_PUB_LEN, ed25519_public_get(org->signing, MANAGEDBUF(32)), MANAGEDBUF(34)), prime_field_write(PRIME_ORG_SIGNET, 3, SECP256K1_KEY_PUB_LEN, secp256k1_public_get(org->encryption, MANAGEDBUF(33)), MANAGEDBUF(35)), prime_field_write(PRIME_ORG_SIGNET, 4, ED25519_SIGNATURE_LEN, org->signature, MANAGEDBUF(65))) != 134) { return false; } return hash_sha512(holder, output); }
void *handle_conn(void *arg) { st_netfd_t client; client = (st_netfd_t)arg; arg = NULL; char buff[1024]; int len = sizeof(buff) / sizeof(buff[0]); int received; received = st_read(client, buff, len, ST_UTIME_NO_TIMEOUT); // fprintf(stdout, "%s\n", buff); st_netfd_t STDOUT; STDOUT = st_netfd_open(STDOUT_FILENO); st_write(STDOUT, buff, sizeof(buff), ST_UTIME_NO_TIMEOUT); received = st_write(client, buff, received, ST_UTIME_NO_TIMEOUT); st_netfd_close(client); return 0; }
bool SMUSync::LoginPlat(st_netfd_t fd, const PlatLoginInfo& plat) { DMXml xml; bool flag = true; std::string msg; char RecvBuf[2048] = {}; UINT32 RecvLen = 0; xml.NewRoot("soap:Envelope") ->SetTextAttribute("xmlns:soap", "http://www.w3.org/2003/05/soap-envelope") ->SetTextAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") ->SetTextAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema") ->SetTextAttribute("xmlns:soapenc", "http://schemas.xmlsoap.org/soap/encoding/") ->NewChild("soap:Body", 0) ->NewChild("Authenticate", 0) ->SetTextAttribute("xmlns","http://see1000.com/service") ->NewChild("name", plat.PlatUserName.c_str())->GetParent() ->NewChild("pass", plat.PlatPwd.c_str()); std::string body = xml.Encode(); //PacketPlatServer("Authenticate", body); do { if (st_write(fd, msg.c_str(), msg.length(),-1)<0) { flag = true; break; } if (st_read(fd, RecvBuf, 2048, -1)<0) { flag = false; break; } /* { std::string result = ParseWebService(RecvBuf, "AuthenticateResult"); if(result.compare("true")) { return false; } }*/ } while (0); return flag; }
hoxResult hoxSocketAPI::write_string( const st_netfd_t nfd, const std::string& sData ) { const int nSize = sData.size(); if ( nSize != st_write( nfd, sData.c_str(), nSize, ST_UTIME_NO_TIMEOUT ) ) { hoxLog(LOG_SYS_WARN, "%s: Failed to write using st_write", __FUNCTION__); return hoxRC_ERR; } return hoxRC_OK; }
bool_t org_signet_verify(prime_org_signet_t *org) { stringer_t *holder = MANAGEDBUF(69); if (!org || !org->signing || !org->encryption || !org->signature || st_length_get(org->signature) != 64) { return false; } else if (st_write(holder, prime_field_write(PRIME_ORG_SIGNET, 1, ED25519_KEY_PUB_LEN, ed25519_public_get(org->signing, MANAGEDBUF(32)), MANAGEDBUF(34)), prime_field_write(PRIME_ORG_SIGNET, 3, SECP256K1_KEY_PUB_LEN, secp256k1_public_get(org->encryption, MANAGEDBUF(33)), MANAGEDBUF(35))) != 69) { return false; } else if (ed25519_verify(org->signing, holder, org->signature)) { return false; } return true; }
void task15(void* arg) { st_netfd_t rfd = st_open("/Users/vss/projects/1.gz", O_RDONLY, S_IRUSR); st_netfd_t wfd = st_open("/Users/vss/projects/tmp.gz", O_WRONLY, S_IWUSR); for (long w = 0; w < 3; ++w) { char buffer[32096]; const char str[] = "Of course, take it!"; char response[1024 + sizeof(str)]; int rc = 0; int c = 0; while (c < sizeof(buffer)) { if ((rc = st_read(rfd, buffer + c, std::min<int>(4, sizeof(buffer) - c), -1)) <= 0) { std::cout << "st_read " << rc << " " << strerror(rc) << std::endl; exit(1); } c += rc; } if ((rc = st_mutex_lock(test4_mutex)) != 0) { std::cout << "st_mutex_lock " << rc << " " << strerror(rc) << std::endl; exit(1); } for (int i = 0; i < sizeof(response); i += sizeof(str)) { memcpy(response + i, str, sizeof(str)); } if ((rc = st_mutex_unlock(test4_mutex)) != 0) { std::cout << "st_mutex_unlock " << rc << " " << strerror(rc) << std::endl; exit(1); } if ((rc = st_write(wfd, response, sizeof(response), -1)) <= 0) { std::cout << "st_write " << rc << " " << strerror(rc) << std::endl; exit(1); } } st_netfd_close(rfd); st_netfd_close(wfd); }
int SrsSocket::write(const void* buf, size_t size, ssize_t* nwrite) { int ret = ERROR_SUCCESS; *nwrite = st_write(stfd, (void*)buf, size, send_timeout); if (*nwrite <= 0) { if (errno == ETIME) { return ERROR_SOCKET_TIMEOUT; } return ERROR_SOCKET_WRITE; } send_bytes += *nwrite; return ret; }
/* * Session handling function stub. Just dumps small HTML page. */ void handle_session(long srv_socket_index, st_netfd_t cli_nfd) { static char resp[] = "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n" "Connection: close\r\n\r\n<H2>It worked!</H2>\n"; char buf[512]; int n = sizeof(resp) - 1; struct in_addr *from = st_netfd_getspecific(cli_nfd); if (st_read(cli_nfd, buf, sizeof(buf), SEC2USEC(REQUEST_TIMEOUT)) < 0) { err_sys_report(errfd, "WARN: can't read request from %s: st_read", inet_ntoa(*from)); return; } if (st_write(cli_nfd, resp, n, ST_UTIME_NO_TIMEOUT) != n) { err_sys_report(errfd, "WARN: can't write response to %s: st_write", inet_ntoa(*from)); return; } RQST_COUNT(srv_socket_index)++; }
int SrsStSocket::write(void* buf, size_t size, ssize_t* nwrite) { int ret = ERROR_SUCCESS; ssize_t nb_write = st_write(stfd, buf, size, send_timeout); if (nwrite) { *nwrite = nb_write; } // On success a non-negative integer equal to nbyte is returned. // Otherwise, a value of -1 is returned and errno is set to indicate the error. if (nb_write <= 0) { // @see https://github.com/simple-rtmp-server/srs/issues/200 if (nb_write < 0 && errno == ETIME) { return ERROR_SOCKET_TIMEOUT; } return ERROR_SOCKET_WRITE; } send_bytes += nb_write; return ret; }
void *_peer_task_worker(void *arg) { struct rpc_package_head *task; task = (struct rpc_package_head*)arg; arg = NULL; LOG("[%d] 处理一个 %d -> %d 的RPC 业务 #%d\n", self_index, task->source, task->destination, task->id); // TODO: 编写业务的通用处理办法 struct rpc_package_head *response; response = protocol_package_create(RESPONSE, task->destination, task->source, task->id, "任务完成!Mission Completeion!", NULL); rpcpkg_len pkg_len, sended; char *data; struct peer_info *peer_info; peer_info = &peer_list[response->destination]; data = protocol_encode(response, &pkg_len); protocol_package_free(response); response = NULL; if ((sended = st_write(peer_info->rpc_fd, data, pkg_len, ST_UTIME_NO_TIMEOUT)) != pkg_len) { ERR("[%d] 写回 RPC 包长度 %d 与原包长 %d 不符,错误信息:%s\n", self_index, sended, pkg_len, strerror(errno)); } free(data); data = NULL; // 清理和结束 protocol_package_free(task); task = NULL; worker_thread_count --; return 0; }
static void *handle_request(void *arg) { struct pollfd pds[2]; st_netfd_t cli_nfd, rmt_nfd; int sock, n; char buf[IOBUFSIZE]; cli_nfd = (st_netfd_t) arg; pds[0].fd = st_netfd_fileno(cli_nfd); pds[0].events = POLLIN; /* Connect to remote host */ if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { print_sys_error("socket"); goto done; } if ((rmt_nfd = st_netfd_open_socket(sock)) == NULL) { print_sys_error("st_netfd_open_socket"); close(sock); goto done; } if (st_connect(rmt_nfd, (struct sockaddr *)&rmt_addr, sizeof(rmt_addr), -1) < 0) { print_sys_error("st_connect"); st_netfd_close(rmt_nfd); goto done; } pds[1].fd = sock; pds[1].events = POLLIN; /* Now just pump the data through */ for ( ; ; ) { pds[0].revents = 0; pds[1].revents = 0; if (st_poll(pds, 2, -1) <= 0) { print_sys_error("st_poll"); break; } if (pds[0].revents & POLLIN) { if ((n = (int) st_read(cli_nfd, buf, IOBUFSIZE, -1)) <= 0) break; if (st_write(rmt_nfd, buf, n, -1) != n) break; } if (pds[1].revents & POLLIN) { if ((n = (int) st_read(rmt_nfd, buf, IOBUFSIZE, -1)) <= 0) break; if (st_write(cli_nfd, buf, n, -1) != n) break; } } st_netfd_close(rmt_nfd); done: st_netfd_close(cli_nfd); return NULL; }
void *probe(void *data) { int sock, len; struct sockaddr_in rmt; st_netfd_t rmt_nfd; struct probedef *probe = (struct probedef *)data; char buffer[1024]; st_utime_t start; ST_INITIATE(110); start = st_utime(); if (debug > 3) fprintf(stderr, "Connecting to: %s\n", probe->ipaddress); if (st_connect(rmt_nfd, (struct sockaddr *)&rmt, sizeof(rmt), TIMEOUT) < 0) { char buf[256]; sprintf(buf, "%s(%d): %s", probe->ipaddress, __LINE__, strerror(errno)); probe->connect = ((float) (st_utime() - start)) * 0.000001; probe->msg = strdup(buf); LOG(LOG_DEBUG, probe->msg); if (debug > 3) fprintf(stderr, "%s: %s\n", probe->ipaddress, probe->msg); goto err_close; } probe->connect = ((float) (st_utime() - start)) * 0.000001; // expect here: +OK POP3 xxx.xxxxxxx.xx v2000.70rh server ready memset(buffer, 0, sizeof(buffer)); len = st_read(rmt_nfd, buffer, sizeof(buffer), TIMEOUT); if (len == -1) { ST_ERROR("read", TIMEOUT); goto err_close; } if (debug > 3) fprintf(stderr, "< %s", buffer); if (buffer[0] != '+') { probe->msg = strdup(buffer); goto err_close; } if (probe->username == NULL || probe->username[0] == 0) { probe->msg = strdup("missing username"); goto err_close; } sprintf(buffer, "USER %s\n", probe->username); if (debug > 3) fprintf(stderr, "> %s", buffer); len = st_write(rmt_nfd, buffer, strlen(buffer), TIMEOUT); if (len == -1) { ST_ERROR("write", TIMEOUT); goto err_close; } // expect here: +OK User name accepted, password please memset(buffer, 0, sizeof(buffer)); len = st_read(rmt_nfd, buffer, sizeof(buffer), TIMEOUT); if (len == -1) { ST_ERROR("read", TIMEOUT); goto err_close; } if (debug > 3) fprintf(stderr, "< %s", buffer); if (buffer[0] != '+') { probe->msg = strdup(buffer); goto err_close; } sprintf(buffer, "PASS %s\n", probe->password); if (debug > 3) fprintf(stderr, "> %s", buffer); len = st_write(rmt_nfd, buffer, strlen(buffer), TIMEOUT); if (len == -1) { ST_ERROR("write", TIMEOUT); goto err_close; } // expect here: +OK Mailbox open, 62 messages memset(buffer, 0, sizeof(buffer)); len = st_read(rmt_nfd, buffer, sizeof(buffer), TIMEOUT); if (len == -1) { ST_ERROR("read", TIMEOUT); goto err_close; } if (debug > 3) fprintf(stderr, "< %s", buffer); if (buffer[0] != '+') { probe->msg = strdup(buffer); goto err_close; } sprintf(buffer, "QUIT\n"); if (debug > 3) fprintf(stderr, "> %s", buffer); len = st_write(rmt_nfd, buffer, strlen(buffer), TIMEOUT); if (len == -1) { ST_ERROR("write", TIMEOUT); goto err_close; } // expect here: +OK Sayonara memset(buffer, 0, sizeof(buffer)); len = st_read(rmt_nfd, buffer, sizeof(buffer), TIMEOUT); if (len == -1) { ST_ERROR("read", TIMEOUT); goto err_close; } if (debug > 3) fprintf(stderr, "< %s", buffer); if (buffer[0] != '+') { probe->msg = strdup(buffer); goto err_close; } err_close: st_netfd_close(rmt_nfd); probe->total = ((float) (st_utime() - start)) * 0.000001; done: thread_count--; return NULL; }
/*--------------------------------------------------------------------------- * *--------------------------------------------------------------------------*/ int send_scsi_command(char *buffer, scsi_command_t *s, int cmd_id) { #ifdef DIXTRAC_LINUX_SG int cmd_len,status = 0; #ifdef LINUX_SG_IO sg_io_hdr_t sgio_hdr; #else uint in_size,out_size; struct sg_header *sg_hd; char *buf_pointer; #endif #ifndef SG_TIMER struct timeval start; struct timezone tz; #endif #ifdef WRITE_CHECK assert((s->command.opcode!=WRITE_6) && (s->command.opcode!=WRITE_10)); #endif cmd_len = s->length; /* safety checks */ if (!cmd_len) return -1; /* need a cmd_len != 0 */ if (!buffer) return -1; /* check argument to be != NULL */ /* printf("SCSI command 0x%2X: length %d, datalen %d\n",s->command.opcode, */ /* s->length,s->datalen); */ #ifdef LINUX_SG_IO memset((void *) &sgio_hdr, 0, sizeof(sg_io_hdr_t)); sgio_hdr.interface_id = 'S'; sgio_hdr.cmd_len = cmd_len; sgio_hdr.iovec_count = 0; sgio_hdr.mx_sb_len = sizeof(sense_buffer); if (scsi_command_type (s->command.opcode) == SCSI_DATA_IN) sgio_hdr.dxfer_direction = SG_DXFER_FROM_DEV; else sgio_hdr.dxfer_direction = SG_DXFER_TO_DEV; sgio_hdr.dxfer_len = s->datalen; sgio_hdr.dxferp = (void *) buffer; sgio_hdr.cmdp = (unsigned char *) &(s->command); sgio_hdr.sbp = (unsigned char *) sense_buffer; sgio_hdr.timeout = SG_IO_TIMEOUT; sgio_hdr.pack_id = cmd_id; sgio_hdr.flags = SG_FLAG_DIRECT_IO; #else /* adjust pointer to buffer passed to write so that we can prepend the data in buffer with the SCSI command */ buf_pointer = buffer - cmd_len; /* copy the command */ memcpy(buf_pointer,(char *) &s->command,s->length ); if (scsi_command_type (s->command.opcode) == SCSI_DATA_IN) { in_size = 0; out_size = s->datalen; } else { in_size = s->datalen; out_size = 0; /* copy the additional data to be sent */ /* memcpy(in_buffer + SCSI_OFFSET + s->length,buffer,in_size); */ } /* make sure we are sending at most # of bytes handled by sg driver */ if (SG_HDR_OFFSET + cmd_len + in_size > SG_BIG_BUFF) return -1; if (SG_HDR_OFFSET + out_size > SG_BIG_BUFF) { out_size = SG_BIG_BUFF-SG_HDR_OFFSET; /* printf("exec_scsi_command: Warning - can retrieve only %d KB of data\n", out_size / 1024); */ } /* make buf_pointer point to the begining of the buffer given to write */ buf_pointer -= SG_HDR_OFFSET; /* generic SCSI device header construction */ sg_hd = (struct sg_header *) buf_pointer; sg_hd->reply_len = SG_HDR_OFFSET + out_size; sg_hd->twelve_byte = (cmd_len == 12); sg_hd->pack_id = cmd_id; sg_hd->result = 0; #endif #ifndef SG_TIMER gettimeofday(&start,&tz); #endif #ifdef LINUX_SG_IO /* send command */ #ifdef STATE_THREADS status = st_write(scsidev_fd, &sgio_hdr, sizeof(sg_io_hdr_t),ST_TIMEOUT); #else status = write(scsidev_fd, &sgio_hdr, sizeof(sg_io_hdr_t)); #endif if ( status < 0 || (status < sizeof(sg_io_hdr_t))) { /* some error happened */ fprintf( stderr, "write(sg_io) result = 0x%x cmd = 0x%x\n", status, s->command.opcode ); } #else /* send command */ status = write(scsidev_fd, buf_pointer, SG_HDR_OFFSET + cmd_len + in_size); if ( status < 0 || status != SG_HDR_OFFSET + cmd_len + in_size || sg_hd->result ) { /* some error happened */ fprintf( stderr, "write(generic) result = 0x%x cmd = 0x%x\n", sg_hd->result, s->command.opcode ); } #endif #ifdef SG_TIMER // printf("%s() (%d,%d)\n", __func__, sgio_hdr.duration.tv_sec, // sgio_hdr.duration.tv_usec); #ifdef LINUX_SG_IO ustart = sgio_hdr.duration.tv_usec; ustart_sec = sgio_hdr.duration.tv_sec; #else ustart = sg_hd->time.tv_usec; ustart_sec = sg_hd->time.tv_sec; #endif #else ustart = start.tv_usec; ustart_sec = start.tv_sec; #endif return status; /* DIXTRAC_LINUX_SG */ #endif #ifdef DIXTRAC_FREEBSD_CAM union ccb ccb; int flags; int rc; char cmd_spec[30]; struct timeval start; struct timeval stop; struct timezone tz; flags = (scsi_command_type (s->command.opcode) == SCSI_DATA_IN) ? CAM_DIR_IN : CAM_DIR_OUT; ccb.ccb_h.path_id = cam_device.path_id; ccb.ccb_h.target_id = cam_device.target_id; ccb.ccb_h.target_lun = cam_device.target_lun; /* The following command must be included to make CAM work */ sprintf(cmd_spec,""); for(rc=0;rc<s->length;rc++) { sprintf(cmd_spec,"%s v",cmd_spec); } csio_build(&ccb.csio, /* data_ptr */ buffer, /* dxfer_len */ s->datalen, /* flags */ flags | CAM_DEV_QFRZDIS, /* retry_count */ 0, /* timeout */ 5000, /* cmd_spec...*/ cmd_spec, ((char *) &s->command)[0],((char *) &s->command)[1], ((char *) &s->command)[2],((char *) &s->command)[3], ((char *) &s->command)[4],((char *) &s->command)[5], ((char *) &s->command)[6],((char *) &s->command)[7], ((char *) &s->command)[8],((char *) &s->command)[9], ((char *) &s->command)[10],((char *) &s->command)[11], ((char *) &s->command)[12],((char *) &s->command)[13], ((char *) &s->command)[14],((char *) &s->command)[15] ); gettimeofday(&start,&tz); ustart = start.tv_usec; ustart_sec = start.tv_sec; rc = cam_send_ccb(&cam_device, &ccb); gettimeofday(&stop,&tz); ustop_sec = stop.tv_sec; ustop = stop.tv_usec; if (rc < 0 || (ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { fprintf(stderr, "Error: cam_send_ccb (rc=%d)\n", rc); if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) { fprintf(stderr, "Printing sense buffer\n"); scsi_sense_print(&cam_device, &ccb.csio, stderr); } return -1; } return 0; /* DIXTRAC_FREEBSD_CAM */ #endif }
int pushto(st_netfd_t rmt_nfd, struct thr_data *td) { FILE *in; char buffer[BUFSIZ]; struct stat st; int filesize; int i, len; struct q_info *q = td->q; char *basename; if ((basename = strrchr(td->filename, '/')) == NULL) { basename = td->filename; } else { basename++; } if (stat(td->filename, &st)) { LOG(LOG_WARNING, "%s: %m", td->filename); return 0; } filesize = (int) st.st_size; if (filesize == 0) { LOG(LOG_WARNING, "zero size: %s", td->filename); return 1; } // expect: +OK UpWatch Acceptor vx.xx. Please login memset(buffer, 0, sizeof(buffer)); len = st_read(rmt_nfd, buffer, sizeof(buffer), TIMEOUT); if (len == -1) { if (errno == ETIME) { LOG(LOG_WARNING, "timeout reading login request string"); } else { LOG(LOG_WARNING, "read: %m"); } return 0; } if (debug > 3) fprintf(stderr, "%s[%u] < %s", q->host, st_netfd_fileno(rmt_nfd), buffer); if (buffer[0] != '+') { LOG(LOG_WARNING, buffer); return 0; } sprintf(buffer, "USER %s\n", q->user); uw_setproctitle("%s:%d %s", q->host, q->port, buffer); if (debug > 3) fprintf(stderr, "%s[%u] > %s", q->host, st_netfd_fileno(rmt_nfd), buffer); len = st_write(rmt_nfd, buffer, strlen(buffer), TIMEOUT); if (len == -1) { if (errno == ETIME) { LOG(LOG_WARNING, "timeout writing %s", buffer); } else { LOG(LOG_WARNING, "write: %m"); } return 0; } // expect here: +OK Please enter password memset(buffer, 0, sizeof(buffer)); len = st_read(rmt_nfd, buffer, sizeof(buffer), TIMEOUT); if (len == -1) { if (errno == ETIME) { LOG(LOG_WARNING, "timeout reading OK enter password"); } else { LOG(LOG_WARNING, "read: %m"); } return 0; } if (debug > 3) fprintf(stderr, "%s[%u] < %s", q->host, st_netfd_fileno(rmt_nfd), buffer); if (buffer[0] != '+') { LOG(LOG_WARNING, buffer); return 0; } sprintf(buffer, "PASS %s\n", q->pwd); uw_setproctitle("%s:%d PASS xxxxxxxx", q->host, q->port); if (debug > 3) fprintf(stderr, "%s[%u] > %s", q->host, st_netfd_fileno(rmt_nfd), buffer); len = st_write(rmt_nfd, buffer, strlen(buffer), TIMEOUT); if (len == -1) { if (errno == ETIME) { LOG(LOG_WARNING, "timeout writing %s", buffer); } else { LOG(LOG_WARNING, "write: %m"); } return 0; } // expect here: +OK logged in, enter command memset(buffer, 0, sizeof(buffer)); len = st_read(rmt_nfd, buffer, sizeof(buffer), TIMEOUT); if (len == -1) { if (errno == ETIME) { LOG(LOG_WARNING, "timeout reading enter command"); } else { LOG(LOG_WARNING, "read: %m"); } return 0; } if (debug > 3) fprintf(stderr, "%s[%u] < %s", q->host, st_netfd_fileno(rmt_nfd), buffer); if (buffer[0] != '+') { LOG(LOG_WARNING, buffer); return 0; } sprintf(buffer, "DATA %d %s\n", filesize, basename); uw_setproctitle("%s:%d %s", q->host, q->port, buffer); if (debug > 3) fprintf(stderr, "%s[%u] > %s", q->host, st_netfd_fileno(rmt_nfd), buffer); len = st_write(rmt_nfd, buffer, strlen(buffer), TIMEOUT); if (len == -1) { if (errno == ETIME) { LOG(LOG_WARNING, "timeout writing %s", buffer); } else { LOG(LOG_WARNING, "write: %m"); } return 0; } // expect here: +OK start sending your file memset(buffer, 0, sizeof(buffer)); len = st_read(rmt_nfd, buffer, sizeof(buffer), TIMEOUT); if (len == -1) { if (errno == ETIME) { LOG(LOG_WARNING, "timeout reading DATA response"); } else { LOG(LOG_WARNING, "read: %m"); } return 0; } if (debug > 3) fprintf(stderr, "%s[%u] < %s", q->host, st_netfd_fileno(rmt_nfd), buffer); if (buffer[0] != '+') { LOG(LOG_WARNING, buffer); return 0; } if ((in = fopen(td->filename, "r")) == NULL) { LOG(LOG_ERR, "can't open %s", td->filename); return 0; } uw_setproctitle("%s:%d: UPLOADING, size=%u %s", q->host, q->port, filesize, td->filename); while ((i = fread(buffer, 1, sizeof(buffer), in)) == sizeof(buffer)) { //LOG(LOG_DEBUG, "read %d from input", i); len = st_write(rmt_nfd, buffer, i, TIMEOUT); if (len == -1) { if (errno == ETIME) { LOG(LOG_WARNING, "timeout writing %s", buffer); } else { LOG(LOG_WARNING, "write: %m"); } fclose(in); return 0; } //LOG(LOG_DEBUG, "written %d to output", len); } if (!feof(in)) { LOG(LOG_ERR, "fread: %m"); fclose(in); return 0; } if (i>0 && st_write(rmt_nfd, buffer, i, TIMEOUT) != i) { LOG(LOG_ERR, "socket write error: %m"); fclose(in); return 0; } fclose(in); // expect here: +OK Thank you. Enter command memset(buffer, 0, sizeof(buffer)); len = st_read(rmt_nfd, buffer, sizeof(buffer), TIMEOUT); if (len == -1) { if (errno == ETIME) { LOG(LOG_WARNING, "timeout reading enter command"); } else { LOG(LOG_WARNING, "read: %m"); } return 0; } if (debug > 3) fprintf(stderr, "%s[%u] < %s", q->host, st_netfd_fileno(rmt_nfd), buffer); if (buffer[0] != '+') { LOG(LOG_WARNING, buffer); return 0; } sprintf(buffer, "QUIT\n"); uw_setproctitle("%s:%d %s", q->host, q->port, buffer); if (debug > 3) fprintf(stderr, "%s[%u] > %s", q->host, st_netfd_fileno(rmt_nfd), buffer); len = st_write(rmt_nfd, buffer, strlen(buffer), TIMEOUT); if (len == -1) { if (errno == ETIME) { LOG(LOG_WARNING, "timeout writing %s", buffer); } else { LOG(LOG_WARNING, "write: %m"); } return 0; } // expect here: +OK Nice talking to you. Bye memset(buffer, 0, sizeof(buffer)); len = st_read(rmt_nfd, buffer, sizeof(buffer), TIMEOUT); if (len == -1) { if (errno == ETIME) { LOG(LOG_WARNING, "timeout reading QUIT response", buffer); } else { LOG(LOG_WARNING, "read: %m"); } return 0; } if (debug > 3) fprintf(stderr, "%s[%u] < %s", q->host, st_netfd_fileno(rmt_nfd), buffer); return 1; }
static void *link_to_peers(void *arg) { int client_fd, index, rv; st_netfd_t client; struct addrinfo hints, *ai, *p; const char *host = "0.0.0.0"; fprintf(stderr, "link to perrs\n"); for (int i=0; i<vp_count; i++) { if (i == my_index) continue; char port[16]; //snprintf(port, 16 - 1, "%d", RPC_PORT + i); index = RPC_PORT + i; sprintf(port, "%d", index); memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ((rv = getaddrinfo(host, port, &hints, &ai)) != 0) { fprintf(stderr, "[%d] failed to getaddrinfo to peer #%d\n", my_index, i); continue; } for (p = ai; p != NULL; p = p->ai_next) { if ((client_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { continue; } if ((client = st_netfd_open(client_fd)) == NULL) { close(client_fd); continue; } if ((rv = st_connect(client, p->ai_addr, p->ai_addrlen, ST_UTIME_NO_TIMEOUT)) != 0) { st_netfd_close(client); close(client_fd); continue; } else { fd_list[i] = client; } // 写入 1 字节的 rpc 握手头 if ((rv = st_write(client, (char *)&my_index, 1, ST_UTIME_NO_TIMEOUT)) == -1) { fprintf(stderr, "[%d] handshake failed.\n", my_index); } fd_list[i] = client; break; } if (p == NULL) { fprintf(stderr, "[%d] failed to connect to peer #%d.\n", my_index, i); } freeaddrinfo(ai); ai = NULL; p = NULL; // 模拟:发出第一个 rpc 包 char message[] = "hello rpc."; rpcpkg_len len = strlen(message); rpcpkg_len nlen = HTON(len); // network order of len char *package = (char*)calloc(sizeof(rpcpkg_len) + len, sizeof(char)); memcpy(package, &nlen, sizeof(len)); memcpy(package + sizeof(len), message, len); fprintf(stdout, "[%d] construction an package: << ", my_index); for (int j=0; j<len + sizeof(len); j++) { fprintf(stdout, "%02X ", *((uint8_t*)package + j)); } fprintf(stdout, " >>\n"); if ((rv = st_write(client, package, len + sizeof(rpcpkg_len), ST_UTIME_NO_TIMEOUT)) == -1) { fprintf(stderr, "[%d] failed to write package into client\n", my_index); } free(package); } return NULL; }
hoxResult hoxDbClient::WWW_authenticate( const std::string& sPlayerId, const std::string& sHPassword ) { const char* FNAME = "hoxDbClient::WWW_authenticate"; hoxResult result = hoxRC_ERR; hoxLog(LOG_DEBUG, "%s: ENTER. pid = [%s].", FNAME, sPlayerId.c_str()); /* Open the socket connect to the server. */ const char* szHost = WWW_HOST; const int nPort = WWW_PORT; st_netfd_t nfd = NULL; nfd = _open_client_socket( szHost, nPort ); if ( nfd == NULL ) { hoxLog(LOG_ERROR, "%s: Failed to open a client socket to [%s:%d].", FNAME, szHost, nPort); return hoxRC_ERR; } /* Send the request. */ std::string sRequest; sRequest = std::string("GET /blog/hoxchess-login.php") + "?pid=" + sPlayerId + "&password="******" HTTP/1.0\r\n" + "Host: " + szHost + "\r\n" + "Content-Length: 0\r\n" + "\r\n"; const int nToSend = sRequest.size(); ssize_t nSent = 0; hoxLog(LOG_DEBUG, "%s: Sending (%d bytes): [\n%s]...", FNAME, sRequest.size(), sRequest.c_str()); nSent = st_write( nfd, sRequest.c_str(), nToSend, ST_UTIME_NO_TIMEOUT ); if ( nSent < nToSend ) { hoxLog(LOG_SYS_WARN, "%s: Failed to write to socket", FNAME); st_netfd_close( nfd ); return hoxRC_OK; } /* Read the response back. */ hoxLog(LOG_DEBUG, "%s: Reading response...", FNAME); std::string sResponse; ssize_t nRead = 0; const int MAX_TO_READ = 512; // *** Hard-coded max-buffer-size. char szBuffer[MAX_TO_READ]; for (;;) { memset( szBuffer, 0, MAX_TO_READ ); // zero-out. nRead = st_read( nfd, szBuffer, MAX_TO_READ, ST_UTIME_NO_TIMEOUT ); if ( nRead > 0 ) { sResponse.append( szBuffer, nRead ); } else if ( nRead != MAX_TO_READ ) // Connection closed? { break; // Done } } hoxLog(LOG_DEBUG, "%s: Received (%d bytes): [\n%s].", FNAME, sResponse.size(), sResponse.c_str()); /* Check for return-code. */ std::string::size_type npBody = sResponse.find("\r\n\r\n"); if ( npBody != std::string::npos && sResponse.substr(npBody+4).find_first_of('0') == 0 ) { result = hoxRC_OK; } /* Cleanup and return. */ st_netfd_close( nfd ); return result; }
void * handle_connection(void *fd2) { int rc, n, len; int ffd; char *buf, *fn; int i; st_netfd_t fd = (st_netfd_t)fd2; buf = malloc(4096); rc = 0; again: rc += st_read(fd, buf + rc, 4096 - rc,-1); if(rc < 0) { perror("st_read"); goto fail; } if(rc < 4) goto fail; if(memcmp(buf, "GET ", 4) != 0) goto fail; for(i = 5; i < rc; i++) if(buf[i] == ' ' || buf[i] == '\r' || buf[i] == '\n') break; if(i == rc && rc < 4096) goto again; len = strlen(root); fn = malloc(len + 1 + i - 5 + 12); strcpy(fn, root); memcpy(fn + len, buf + 5, i - 5); if(buf[i - 1] == '/') strcpy(fn + len + i - 5, "index.html"); else fn[len + i - 5] = '\0'; i--; search: while(i < rc - 3) if(buf[i++] == '\r' && buf[i] == '\n'){ i++; if(buf[i++] == '\r' && buf[i] == '\n') goto send; } if(rc < 4096) { rc += st_read(fd, buf + rc, 4096 - rc,-1); goto search; } send: #ifdef STATIC rc = st_write(fd, &resp, resp_size, 60000000); if(rc != resp_size) { perror("st_write"); goto fail; } #else ffd = open(fn, O_RDONLY,0); if(ffd < 0) { int err; char *message; if(errno == ENOENT) { err = 404; message = "File doesn't exist"; } else if(errno == EACCES || errno == EPERM) { err = 403; message = "Forbidden"; } else if(errno == EMFILE || errno == ENFILE) { err = 500; message = "Out of file descriptors"; } else if(errno == ENOMEM) { err = 500; message = "Out of memory"; } else { err = 500; message = "Unknown error"; } n = snprintf(buf, 4096, "HTTP/1.1 %d %s\r\n" "Content-Type: text/html\r\n" "Server: Trivial-st\r\n" "Connection: close\r\n" "\r\n" "<html><body><p>Couldn't open %s: %s</body></html>\r\n", err, message, fn, message); free(fn); } else { free(fn); n = snprintf(buf, 4096, "HTTP/1.1 200 OK\r\n" "Content-Type: text/html\r\n" "Server: Trivial-st\r\n" "Connection: close\r\n" "\r\n"); rc = read(ffd, buf + n, 4096 - n); if(rc >= 0) n += rc; } rc = st_write(fd, buf, n,-1); if(rc < 0) { perror("write"); if(ffd >= 0) close(ffd); goto fail; } if(ffd >= 0) { while(1) { n = read(ffd, buf, 4096); if(n <= 0) break; rc = st_write(fd, buf, 4096,-1); st_sleep(0); } } close(ffd); #endif fail: st_netfd_close(fd); free(buf); st_thread_exit(NULL); }
ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size, st_utime_t timeout) { ssize_t n, rv; size_t nleft, nbyte; int index, iov_cnt; struct iovec *tmp_iov; struct iovec local_iov[_LOCAL_MAXIOV]; /* Calculate the total number of bytes to be sent */ nbyte = 0; for (index = 0; index < iov_size; index++) nbyte += iov[index].iov_len; rv = (ssize_t)nbyte; nleft = nbyte; tmp_iov = (struct iovec *) iov; /* we promise not to modify iov */ iov_cnt = iov_size; while (nleft > 0) { if (iov_cnt == 1) { if (st_write(fd, tmp_iov[0].iov_base, nleft, timeout) != (ssize_t) nleft) rv = -1; break; } if ((n = writev(fd->osfd, tmp_iov, iov_cnt)) < 0) { if (errno == EINTR) continue; if (!_IO_NOT_READY_ERROR) { rv = -1; break; } } else { if ((size_t) n == nleft) break; nleft -= n; /* Find the next unwritten vector */ n = (ssize_t)(nbyte - nleft); for (index = 0; (size_t) n >= iov[index].iov_len; index++) n -= iov[index].iov_len; if (tmp_iov == iov) { /* Must copy iov's around */ if (iov_size - index <= _LOCAL_MAXIOV) { tmp_iov = local_iov; } else { tmp_iov = calloc(1, (iov_size - index) * sizeof(struct iovec)); if (tmp_iov == NULL) return -1; } } /* Fill in the first partial read */ tmp_iov[0].iov_base = &(((char *)iov[index].iov_base)[n]); tmp_iov[0].iov_len = iov[index].iov_len - n; index++; /* Copy the remaining vectors */ for (iov_cnt = 1; index < iov_size; iov_cnt++, index++) { tmp_iov[iov_cnt].iov_base = iov[index].iov_base; tmp_iov[iov_cnt].iov_len = iov[index].iov_len; } } /* Wait until the socket becomes writable */ if (st_netfd_poll(fd, POLLOUT, timeout) < 0) { rv = -1; break; } } if (tmp_iov != iov && tmp_iov != local_iov) free(tmp_iov); return rv; }
void *handle_connection(void *arg) { st_netfd_t client_nfd = (st_netfd_t)arg; struct http_stream *s = http_stream_create(HTTP_SERVER, SEC2USEC(5)); char buf[4*1024]; int error = 0; struct http_stream *cs = NULL; uri_t *u = uri_new(); int should_close = 1; for (;;) { should_close = 1; if (s->status != HTTP_STREAM_OK) break; cs = NULL; error = 0; s->timeout = SEC2USEC(5); int status = http_stream_request_read(s, client_nfd); s->timeout = SEC2USEC(30); // longer timeout for the rest if (status != HTTP_STREAM_OK) { if (s->status == HTTP_STREAM_CLOSED || s->status == HTTP_STREAM_TIMEOUT) { error = 1; } else { error = 400; } goto release; } cs = http_stream_create(HTTP_CLIENT, SEC2USEC(30)); //http_request_debug_print(s->req); fprintf(stderr, "request uri: %s\n", s->req->uri); const char *error_at = NULL; uri_clear(u); if (uri_parse(u, s->req->uri, strlen(s->req->uri), &error_at) == 0) { fprintf(stderr, "uri_parse error: %s\n", error_at); error = 400; goto release; } uri_normalize(u); if (http_stream_connect(cs, u->host, u->port) != HTTP_STREAM_OK) { error = 504; goto release; } http_request_header_remove(s->req, "Accept-Encoding"); http_request_header_remove(s->req, "Proxy-Connection"); /* TODO: need to expose a copy api for http message */ http_request_t *tmp_req = cs->req; cs->req = s->req; char *request_uri = uri_compose_partial(u); char *tmp_uri = s->req->uri; cs->req->uri = request_uri; if (http_stream_request_send(cs) != HTTP_STREAM_OK) { error = 504; goto release; } cs->req = tmp_req; s->req->uri = tmp_uri; free(request_uri); /* TODO: fix this. post might not contain data. probably move this logic into stream */ size_t total = 0; if (g_strcmp0("POST", s->req->method) == 0) { for (;;) { ssize_t nr = sizeof(buf); status = http_stream_read(s, buf, &nr); fprintf(stderr, "server http_stream_read nr: %zd\n", nr); if (nr < 0 || status != HTTP_STREAM_OK) { error = 1; goto release; } if (nr == 0) break; /*fwrite(buf, sizeof(char), nr, stdout);*/ ssize_t nw = st_write(cs->nfd, buf, nr, s->timeout); if (nw != nr) { error=1; goto release; } fprintf(stderr, "st_write nw: %zd\n", nr); total += nr; } fprintf(stderr, "http_stream_read total: %zu\n", total); } if (http_stream_response_read(cs) != HTTP_STREAM_OK) { error = 502; goto release; } /* TODO: properly create a new response and copy headers */ http_response_t *tmp_resp = s->resp; s->resp = cs->resp; s->resp->http_version = "HTTP/1.1"; http_response_header_remove(s->resp, "Content-Length"); http_response_header_remove(s->resp, "Transfer-Encoding"); if (s->resp->status_code != 204) http_response_header_append(s->resp, "Transfer-Encoding", "chunked"); ssize_t nw = http_stream_response_send(s, 0); s->resp = tmp_resp; fprintf(stderr, "http_stream_response_send: %zd\n", nw); if (s->resp->status_code != 204 && (cs->content_size > 0 || cs->transfer_encoding == TE_CHUNKED)) { total = 0; fprintf(stderr, "content size: %zd\n", cs->content_size); for (;;) { ssize_t nr = sizeof(buf); status = http_stream_read(cs, buf, &nr); fprintf(stderr, "client http_stream_read nr: %zd\n", nr); if (nr <= 0 || status != HTTP_STREAM_OK) break; /*fwrite(buf, sizeof(char), nr, stdout);*/ total += nr; if (http_stream_send_chunk(s, buf, nr) != HTTP_STREAM_OK) break; } fprintf(stderr, "written to client: %zu\n", total); if (total > 0 && s->status == HTTP_STREAM_OK) { http_stream_send_chunk_end(s); } else { fprintf(stderr, "for request: %s status: %d\n", s->req->uri, s->status); } } release: if (!error) { if ((g_strcmp0("HTTP/1.1", s->req->http_version) == 0) && (g_strcmp0(http_request_header_getstr(s->req, "Connection"), "close") != 0)) { // if HTTP/1.1 client and no Connection: close, then don't close should_close = 0; } else if (g_strcmp0(http_request_header_getstr(s->req, "Connection"), "keepalive") == 0) { should_close = 0; } } http_request_clear(s->req); uri_clear(u); if (cs) http_stream_close(cs); /* TODO: break loop if HTTP/1.0 and not keep-alive */ if (error) { fprintf(stderr, "ERROR: %d STATUS: %d, exiting\n", error, s->status); /* TODO: use reason string */ if (error >= 400 && s->status != HTTP_STREAM_CLOSED) { http_response_free(s->resp); s->resp = http_response_new(error, "Error"); http_response_header_append(s->resp, "Content-Length", "0"); s->status = HTTP_STREAM_OK; /* TODO: might want to move this logic into http_stream */ http_stream_response_send(s, 0); } break; } if (should_close) break; } fprintf(stderr, "exiting handle_connection (should_close: %u)\n", should_close); uri_free(u); http_stream_close(s); return NULL; }