/** * Complete an asynchronous read with a time out. * * This function causes all outstanding asynchronous read or * write operations to finish immediately, and the handlers for * canceled operations will be passed the * boost::asio::error::operation_aborted error. * * Call will not return unless timeout has exceeded, data has been * been transferred to the buffer or operation has been canceled * * @param buffer The buffer to which data will be placed * @param msTimeout The amount of time(milliseconds) to wait before canceling * @return Returns the number of bytes transferred to the buffer */ std::size_t SerialPort::recv_with_timeout(std::vector<uint8_t>& buffer, uint32_t msTimeout) { utils::Logger::Instance().Trace(FUNCTION_NAME); uint16_t rVal = 0; std::vector<uint8_t> data; data.resize(512); boost::system::error_code ec; serial_port_->cancel(ec); if (recv_buffer_has_data_) recv_buffer(buffer); utils::Logger::Instance().Debug("I/O cancel: %s", ec.message().c_str()); std::future<std::size_t> read_result = serial_port_->async_read_some( boost::asio::buffer(data), boost::asio::use_future); std::future_status status; do { status = read_result.wait_for(std::chrono::milliseconds(msTimeout)); if (status == std::future_status::timeout) { utils::Logger::Instance().Debug("%s\n\t - timeout waiting for data, " "%d ms timeout expired.\n" "\t - canceling async_read_some.", FUNCTION_NAME_CSTR, msTimeout); serial_port_->cancel(ec); if (recv_buffer_has_data_) recv_buffer(buffer); utils::Logger::Instance().Debug("IO cancel: %s", ec.message().c_str()); break; } else if (status == std::future_status::ready) { rVal = read_result.get(); data.resize(rVal); for (const auto& it : data) buffer.push_back(it); break; } else if (status == std::future_status::deferred) { utils::Logger::Instance().Debug("%s\n\t - deferred waiting", FUNCTION_NAME_CSTR); } else { utils::Logger::Instance().Debug("%s\n\t - unknown state while waiting" "for future", FUNCTION_NAME_CSTR); } } while (status != std::future_status::ready); return rVal; }
void bcast(const size_t& root, T& elem) { #ifdef HAS_MPI // Get the mpi rank and size if(mpi_tools::rank() == root) { // serialize the object graphlab::charstream cstrm(128); graphlab::oarchive oarc(cstrm); oarc << elem; cstrm.flush(); char* send_buffer = cstrm->c_str(); int send_buffer_size = cstrm->size(); assert(send_buffer_size >= 0); // send the ammount to send int error = MPI_Bcast(&send_buffer_size, // Send buffer 1, // send count MPI_INT, // send type root, // root rank MPI_COMM_WORLD); assert(error == MPI_SUCCESS); // send the actual data error = MPI_Bcast(send_buffer, // Send buffer send_buffer_size, // send count MPI_BYTE, // send type root, // root rank MPI_COMM_WORLD); assert(error == MPI_SUCCESS); } else { int recv_buffer_size(-1); // recv the ammount the required buffer size int error = MPI_Bcast(&recv_buffer_size, // recvbuffer 1, // recvcount MPI_INT, // recvtype root, // root rank MPI_COMM_WORLD); assert(error == MPI_SUCCESS); assert(recv_buffer_size >= 0); std::vector<char> recv_buffer(recv_buffer_size); error = MPI_Bcast(&(recv_buffer[0]), // recvbuffer recv_buffer_size, // recvcount MPI_BYTE, // recvtype root, // root rank MPI_COMM_WORLD); assert(error == MPI_SUCCESS); // construct the local element namespace bio = boost::iostreams; typedef bio::stream<bio::array_source> icharstream; icharstream strm(&(recv_buffer[0]), recv_buffer.size()); graphlab::iarchive iarc(strm); iarc >> elem; } #else logstream(LOG_FATAL) << "MPI not installed!" << std::endl; #endif } // end of bcast
int MakeGuid::svc() { typed::protocol::RequestGuid request_guid; request_guid.set_request_no(m_request_no); ACE_Time_Value timeout_v(1, 0); ACE_Message_Block recv_buffer(255); MAKE_NEW_PACKET(ps, SMSG_GUID_REQUEST, 0, request_guid.SerializeAsString()); ACE_Time_Value sleep_time(0, 10 * 1000); ACE_Time_Value start_time; ACE_Time_Value diff_time; while (true) { ACE_OS::sleep(sleep_time); { ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, m_guid_info_que_mutex, -1); if (m_guid_info_que.size() > 0) { continue; } } start_time = ACE_OS::gettimeofday(); int send_n = m_sock_stream.send_n(ps->stream(), ps->stream_size()); if (send_n == ps->stream_size()) { bool parsed_packet = false; recv_buffer.crunch(); while (!parsed_packet) { int recv_n = m_sock_stream.recv(recv_buffer.wr_ptr(), recv_buffer.space(), &timeout_v); if (recv_n > 0) { recv_buffer.wr_ptr(recv_n); parsed_packet = parsePack(recv_buffer); if (parsed_packet) { diff_time = ACE_OS::gettimeofday() - start_time; ACE_UINT64 dt = 0; diff_time.to_usec(dt); DEF_LOG_INFO("request time is : <%s>\n", boost::lexical_cast<string>(dt).c_str()); } } else { // error } } } else { // error } } }
/// combine (per-process) messages Opm::DeferredLogger gatherDeferredLogger(const Opm::DeferredLogger& local_deferredlogger) { int num_messages = local_deferredlogger.messages_.size(); int int64_mpi_pack_size; MPI_Pack_size(1, MPI_INT64_T, MPI_COMM_WORLD, &int64_mpi_pack_size); int unsigned_int_mpi_pack_size; MPI_Pack_size(1, MPI_UNSIGNED, MPI_COMM_WORLD, &unsigned_int_mpi_pack_size); // store number of messages; int message_size = unsigned_int_mpi_pack_size; // store 1 int64 per message for flag message_size += num_messages*int64_mpi_pack_size; // store 2 unsigned ints per message for length of tag and length of text message_size += num_messages*2*unsigned_int_mpi_pack_size; for (const auto lm : local_deferredlogger.messages_) { int string_mpi_pack_size; MPI_Pack_size(lm.tag.size(), MPI_CHAR, MPI_COMM_WORLD, &string_mpi_pack_size); message_size += string_mpi_pack_size; MPI_Pack_size(lm.text.size(), MPI_CHAR, MPI_COMM_WORLD, &string_mpi_pack_size); message_size += string_mpi_pack_size; } // Pack local messages. std::vector<char> buffer(message_size); int offset = 0; packMessages(local_deferredlogger.messages_, buffer, offset); assert(offset == message_size); // Get message sizes and create offset/displacement array for gathering. int num_processes = -1; MPI_Comm_size(MPI_COMM_WORLD, &num_processes); std::vector<int> message_sizes(num_processes); MPI_Allgather(&message_size, 1, MPI_INT, message_sizes.data(), 1, MPI_INT, MPI_COMM_WORLD); std::vector<int> displ(num_processes + 1, 0); std::partial_sum(message_sizes.begin(), message_sizes.end(), displ.begin() + 1); // Gather. std::vector<char> recv_buffer(displ.back()); MPI_Allgatherv(buffer.data(), buffer.size(), MPI_PACKED, const_cast<char*>(recv_buffer.data()), message_sizes.data(), displ.data(), MPI_PACKED, MPI_COMM_WORLD); // Unpack. Opm::DeferredLogger global_deferredlogger; global_deferredlogger.messages_ = unpackMessages(recv_buffer, displ); return global_deferredlogger; }
/* Receive the h value */ int recv_h (SOCKET sock, golle_num_t out) { golle_bin_t bin = { 0 }; if (recv_buffer (sock, &bin) != 0) { return 4; } golle_error err = golle_bin_to_num (&bin, out); if (err != GOLLE_OK) { fprintf (stderr, "Failed to convert hex to number.\n"); } golle_bin_clear (&bin); return (int)err; }
void client(int clinx, char *name, long id, int inx) { int ferr; int lerr; int msgid; Util_AA<char> recv_buffer(BUFSIZ); Util_AA<short> recv_buffer3(BUFSIZ); RT results; Util_AA<char> send_buffer(BUFSIZ); Util_AA<short> send_buffer2(BUFSIZ); int send_len; MS_SRE_LDONE sre_ldone; sprintf(&send_buffer, "hello, greetings from %s, name=%s, id=%ld, inx=%d", my_name, name, id, inx); while (clinx >= 0) { strcat(&send_buffer, "!"); clinx--; } send_len = (int) strlen(&send_buffer) + 1; ferr = XMSG_LINK_(TPT_REF(phandle), // phandle &msgid, // msgid &send_buffer2, // reqctrl (ushort) (inx & 1), // reqctrlsize &recv_buffer3, // replyctrl 1, // replyctrlmax &send_buffer, // reqdata (ushort) send_len, // reqdatasize &recv_buffer, // replydata BUFSIZ, // replydatamax (SB_Tag_Type) &send_buffer, // linkertag 0, // pri 0, // xmitclass XMSG_LINK_LDONEQ); // linkopts util_check("XMSG_LINK_", ferr); do { lerr = XWAIT(LDONE, -1); TEST_CHK_WAITIGNORE(lerr); lerr = XMSG_LISTEN_((short *) &sre_ldone, // sre 0, // listenopts 0); // listenertag } while (lerr == XSRETYPE_NOWORK); assert(lerr == XSRETYPE_LDONE); assert(sre_ldone.sre_linkTag == (SB_Tag_Type) &send_buffer); ferr = XMSG_BREAK_(msgid, results.u.s, TPT_REF(phandle)); util_check("XMSG_BREAK_", ferr); assert(results.u.t.ctrl_size == (uint) (inx & 1)); assert(results.u.t.data_size > (strlen(&send_buffer) + 14)); assert(results.u.t.errm == RT_DATA_RCVD); // data printf("%s\n", &recv_buffer); }
void all_gather_impl(const communicator& comm, const T* in_values, int n, T* out_values, int const* sizes, int const* skips, mpl::false_) { int nproc = comm.size(); // first, gather all size, these size can be different for // each process packed_oarchive oa(comm); for (int i = 0; i < n; ++i) { oa << in_values[i]; } std::vector<int> oasizes(nproc); int oasize = oa.size(); BOOST_MPI_CHECK_RESULT(MPI_Allgather, (&oasize, 1, MPI_INTEGER, c_data(oasizes), 1, MPI_INTEGER, MPI_Comm(comm))); // Gather the archives, which can be of different sizes, so // we need to use allgatherv. // Every thing is contiguous, so the offsets can be // deduced from the collected sizes. std::vector<int> offsets(nproc); sizes2offsets(oasizes, offsets); packed_iarchive::buffer_type recv_buffer(std::accumulate(oasizes.begin(), oasizes.end(), 0)); BOOST_MPI_CHECK_RESULT(MPI_Allgatherv, (const_cast<void*>(oa.address()), int(oa.size()), MPI_BYTE, c_data(recv_buffer), c_data(oasizes), c_data(offsets), MPI_BYTE, MPI_Comm(comm))); for (int src = 0; src < nproc; ++src) { int nb = sizes ? sizes[src] : n; int skip = skips ? skips[src] : 0; std::advance(out_values, skip); if (src == comm.rank()) { // this is our local data for (int i = 0; i < nb; ++i) { *out_values++ = *in_values++; } } else { packed_iarchive ia(comm, recv_buffer, boost::archive::no_header, offsets[src]); for (int i = 0; i < nb; ++i) { ia >> *out_values++; } } } }
void server(int whoami, Test_SRE *sre) { static int cnt = 1; int ferr; int len; char *p; Util_AA<char> recv_buffer(BUFSIZ); Util_AA<short> recv_buffer2(BUFSIZ); bool reply = true; if (abortserver) { cnt++; if (cnt >= loop * maxc * maxcp) util_abort_core_free(); } ferr = XMSG_READCTRL_(sre->sre.sre_msgId, // msgid &recv_buffer2, // reqctrl 1); // bytecount util_check("XMSG_READCTRL_", ferr); ferr = XMSG_READDATA_(sre->sre.sre_msgId, // msgid &recv_buffer, // reqdata BUFSIZ); // bytecount util_check("XMSG_READDATA_", ferr); if (verbose) printf("s-%d: received %s\n", whoami, &recv_buffer); strcat(&recv_buffer, "- reply from "); strcat(&recv_buffer, my_name); if (abortserver) { p = index(&recv_buffer, '='); if (atoi(&p[1]) == (loop - 1)) reply = false; } if (reply) { len = 100; if (verbose) printf("s-%d: sending %s\n", whoami, &recv_buffer); XMSG_REPLY_(sre->sre.sre_msgId, // msgid &recv_buffer2, // replyctrl sre->sre.sre_reqCtrlSize, // replyctrlsize &recv_buffer, // replydata (ushort) len, // replydatasize 0, // errorclass NULL); // newphandle } }
void recv(T& elem, const size_t id, const int tag = 0) { #ifdef HAS_MPI // Get the mpi rank and size assert(id < size()); int recv_buffer_size(-1); int dest(id); MPI_Status status; // recv the size int error = MPI_Recv(&recv_buffer_size, 1, MPI_INT, dest, tag, MPI_COMM_WORLD, &status); assert(error == MPI_SUCCESS); assert(recv_buffer_size > 0); std::vector<char> recv_buffer(recv_buffer_size); // recv the actual content error = MPI_Recv(&(recv_buffer[0]), recv_buffer_size, MPI_BYTE, dest, tag, MPI_COMM_WORLD, &status); assert(error == MPI_SUCCESS); // deserialize // Update the local map namespace bio = boost::iostreams; typedef bio::stream<bio::array_source> icharstream; icharstream strm(&(recv_buffer[0]), recv_buffer.size()); graphlab::iarchive iarc(strm); iarc >> elem; #else logstream(LOG_FATAL) << "MPI not installed!" << std::endl; #endif }
void gather(const T& elem, std::vector<T>& results) { #ifdef HAS_MPI // Get the mpi rank and size size_t mpi_size(size()); int mpi_rank(rank()); if(results.size() != mpi_size) results.resize(mpi_size); // Serialize the local map graphlab::charstream cstrm(128); graphlab::oarchive oarc(cstrm); oarc << elem; cstrm.flush(); char* send_buffer = cstrm->c_str(); int send_buffer_size = cstrm->size(); assert(send_buffer_size >= 0); // compute the sizes std::vector<int> recv_sizes(mpi_size, -1); // Compute the sizes int error = MPI_Gather(&send_buffer_size, // Send buffer 1, // send count MPI_INT, // send type &(recv_sizes[0]), // recvbuffer 1, // recvcount MPI_INT, // recvtype mpi_rank, // root rank MPI_COMM_WORLD); assert(error == MPI_SUCCESS); for(size_t i = 0; i < recv_sizes.size(); ++i) assert(recv_sizes[i] >= 0); // Construct offsets std::vector<int> recv_offsets(recv_sizes); int sum = 0, tmp = 0; for(size_t i = 0; i < recv_offsets.size(); ++i) { tmp = recv_offsets[i]; recv_offsets[i] = sum; sum += tmp; } // if necessary realloac recv_buffer std::vector<char> recv_buffer(sum); // recv all the maps error = MPI_Gatherv(send_buffer, // send buffer send_buffer_size, // how much to send MPI_BYTE, // send type &(recv_buffer[0]), // recv buffer &(recv_sizes[0]), // amount to recv // for each cpuess &(recv_offsets[0]), // where to place data MPI_BYTE, mpi_rank, // root rank MPI_COMM_WORLD); assert(error == MPI_SUCCESS); // Update the local map namespace bio = boost::iostreams; typedef bio::stream<bio::array_source> icharstream; icharstream strm(&(recv_buffer[0]), recv_buffer.size()); graphlab::iarchive iarc(strm); for(size_t i = 0; i < results.size(); ++i) { iarc >> results[i]; } #else logstream(LOG_FATAL) << "MPI not installed!" << std::endl; #endif } // end of gather
void all2all(const std::vector<T>& send_data, std::vector<T>& recv_data) { #ifdef HAS_MPI // Get the mpi rank and size size_t mpi_size(size()); ASSERT_EQ(send_data.size(), mpi_size); if(recv_data.size() != mpi_size) recv_data.resize(mpi_size); // Serialize the output data and compute buffer sizes graphlab::charstream cstrm(128); graphlab::oarchive oarc(cstrm); std::vector<int> send_buffer_sizes(mpi_size); for(size_t i = 0; i < mpi_size; ++i) { const size_t OLD_SIZE(cstrm->size()); oarc << send_data[i]; cstrm.flush(); const size_t ELEM_SIZE(cstrm->size() - OLD_SIZE); send_buffer_sizes[i] = ELEM_SIZE; } cstrm.flush(); char* send_buffer = cstrm->c_str(); std::vector<int> send_offsets(send_buffer_sizes); int total_send = 0; for(size_t i = 0; i < send_offsets.size(); ++i) { const int tmp = send_offsets[i]; send_offsets[i] = total_send; total_send += tmp; } // AlltoAll scatter the buffer sizes std::vector<int> recv_buffer_sizes(mpi_size); int error = MPI_Alltoall(&(send_buffer_sizes[0]), 1, MPI_INT, &(recv_buffer_sizes[0]), 1, MPI_INT, MPI_COMM_WORLD); ASSERT_EQ(error, MPI_SUCCESS); // Construct offsets std::vector<int> recv_offsets(recv_buffer_sizes); int total_recv = 0; for(size_t i = 0; i < recv_offsets.size(); ++i){ const int tmp = recv_offsets[i]; recv_offsets[i] = total_recv; total_recv += tmp; } // Do the massive send std::vector<char> recv_buffer(total_recv); error = MPI_Alltoallv(send_buffer, &(send_buffer_sizes[0]), &(send_offsets[0]), MPI_BYTE, &(recv_buffer[0]), &(recv_buffer_sizes[0]), &(recv_offsets[0]), MPI_BYTE, MPI_COMM_WORLD); ASSERT_EQ(error, MPI_SUCCESS); // Deserialize the result namespace bio = boost::iostreams; typedef bio::stream<bio::array_source> icharstream; icharstream strm(&(recv_buffer[0]), recv_buffer.size()); graphlab::iarchive iarc(strm); for(size_t i = 0; i < recv_data.size(); ++i) { iarc >> recv_data[i]; } #else logstream(LOG_FATAL) << "MPI not installed!" << std::endl; #endif } // end of mpi all to all
static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, ioa_addr *peer_addr, int addrnum) { if(no_permissions || (addrnum<1)) return 0; char saddr[129]="\0"; if (verbose) { addr_to_string(peer_addr,(u08bits*)saddr); } stun_buffer request_message, response_message; beg_cp: { int cp_sent = 0; stun_init_request(STUN_METHOD_CREATE_PERMISSION, &request_message); { int addrindex; for(addrindex=0;addrindex<addrnum;++addrindex) { stun_attr_add_addr(&request_message, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, peer_addr+addrindex); } } add_origin(&request_message); if(add_integrity(clnet_info, &request_message)<0) return -1; stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!cp_sent) { int len = send_buffer(clnet_info, &request_message, 0,0); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "create perm sent: %s\n",saddr); } cp_sent = 1; } else { perror("send"); exit(1); } } } ////////////<<==create permission send if(not_rare_event()) return 0; ////////create permission response==>> { int cp_received = 0; while (!cp_received) { int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "cp response received: \n"); } int err_code = 0; u08bits err_msg[129]; if (stun_is_success_response(&response_message)) { cp_received = 1; if(clnet_info->nonce[0]) { if(check_integrity(clnet_info, &response_message)<0) return -1; } if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); } } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { goto beg_cp; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { cp_received = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "create permission error %d (%s)\n", err_code,(char*)err_msg); return -1; } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "unknown create permission response\n"); /* Try again ? */ } } else { perror("recv"); exit(-1); } } } return 0; }
static int turn_channel_bind(int verbose, uint16_t *chn, app_ur_conn_info *clnet_info, ioa_addr *peer_addr) { stun_buffer request_message, response_message; beg_bind: { int cb_sent = 0; if(negative_test) { *chn = stun_set_channel_bind_request(&request_message, peer_addr, (u16bits)random()); } else { *chn = stun_set_channel_bind_request(&request_message, peer_addr, *chn); } add_origin(&request_message); if(add_integrity(clnet_info, &request_message)<0) return -1; stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!cb_sent) { int len = send_buffer(clnet_info, &request_message, 0,0); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "channel bind sent\n"); } cb_sent = 1; } else { perror("send"); exit(1); } } } ////////////<<==channel bind send if(not_rare_event()) return 0; ////////channel bind response==>> { int cb_received = 0; while (!cb_received) { int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "cb response received: \n"); } int err_code = 0; u08bits err_msg[129]; if (stun_is_success_response(&response_message)) { cb_received = 1; if(clnet_info->nonce[0]) { if(check_integrity(clnet_info, &response_message)<0) return -1; } if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success: 0x%x\n", (int) (*chn)); } } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { goto beg_bind; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { cb_received = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "channel bind: error %d (%s)\n", err_code,(char*)err_msg); return -1; } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "unknown channel bind response\n"); /* Try again ? */ } } else { perror("recv"); exit(-1); break; } } } return 0; }
static int clnet_allocate(int verbose, app_ur_conn_info *clnet_info, ioa_addr *relay_addr, int af, char *turn_addr, u16bits *turn_port) { int af_cycle = 0; int reopen_socket = 0; int allocate_finished; stun_buffer request_message, response_message; beg_allocate: allocate_finished=0; while (!allocate_finished && af_cycle++ < 32) { int allocate_sent = 0; if(reopen_socket && !use_tcp) { socket_closesocket(clnet_info->fd); clnet_info->fd = -1; if (clnet_connect(addr_get_port(&(clnet_info->remote_addr)), clnet_info->rsaddr, (u08bits*)clnet_info->ifname, clnet_info->lsaddr, verbose, clnet_info) < 0) { exit(-1); } reopen_socket = 0; } int af4 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4); int af6 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6); uint64_t reservation_token = 0; char* rt = NULL; int ep = !no_rtcp && !dual_allocation; if(!no_rtcp) { if (!never_allocate_rtcp && allocate_rtcp) { reservation_token = ioa_ntoh64(current_reservation_token); rt = (char*) (&reservation_token); } } if(is_TCP_relay()) { ep = -1; } else if(rt) { ep = -1; } else if(!ep) { ep = (((u08bits)random()) % 2); ep = ep-1; } if(!dos) stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility, rt, ep); else stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility, rt, ep); if(bps) stun_attr_add_bandwidth_str(request_message.buf, (size_t*)(&(request_message.len)), bps); if(dont_fragment) stun_attr_add(&request_message, STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0); add_origin(&request_message); if(add_integrity(clnet_info, &request_message)<0) return -1; stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!allocate_sent) { int len = send_buffer(clnet_info, &request_message,0,0); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "allocate sent\n"); } allocate_sent = 1; } else { perror("send"); exit(1); } } ////////////<<==allocate send if(not_rare_event()) return 0; ////////allocate response==>> { int allocate_received = 0; while (!allocate_received) { int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "allocate response received: \n"); } response_message.len = len; int err_code = 0; u08bits err_msg[129]; if (stun_is_success_response(&response_message)) { allocate_received = 1; allocate_finished = 1; if(clnet_info->nonce[0]) { if(check_integrity(clnet_info, &response_message)<0) return -1; } if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); } { int found = 0; stun_attr_ref sar = stun_attr_get_first(&response_message); while (sar) { int attr_type = stun_attr_get_type(sar); if(attr_type == STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS) { if (stun_attr_get_addr(&response_message, sar, relay_addr, NULL) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: !!!: relay addr cannot be received (1)\n", __FUNCTION__); return -1; } else { if (verbose) { ioa_addr raddr; memcpy(&raddr, relay_addr,sizeof(ioa_addr)); addr_debug_print(verbose, &raddr,"Received relay addr"); } if(!addr_any(relay_addr)) { if(relay_addr->ss.sa_family == AF_INET) { if(default_address_family != STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) { found = 1; addr_cpy(&(clnet_info->relay_addr),relay_addr); break; } } if(relay_addr->ss.sa_family == AF_INET6) { if(default_address_family == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) { found = 1; addr_cpy(&(clnet_info->relay_addr),relay_addr); break; } } } } } sar = stun_attr_get_next(&response_message,sar); } if(!found) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: !!!: relay addr cannot be received (2)\n", __FUNCTION__); return -1; } } stun_attr_ref rt_sar = stun_attr_get_first_by_type( &response_message, STUN_ATTRIBUTE_RESERVATION_TOKEN); uint64_t rtv = stun_attr_get_reservation_token_value(rt_sar); current_reservation_token = rtv; if (verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: rtv=%llu\n", __FUNCTION__, (long long unsigned int)rtv); read_mobility_ticket(clnet_info, &response_message); } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { goto beg_allocate; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { allocate_received = 1; if(err_code == 300) { if(clnet_info->nonce[0]) { if(check_integrity(clnet_info, &response_message)<0) return -1; } ioa_addr alternate_server; if(stun_attr_get_first_addr(&response_message, STUN_ATTRIBUTE_ALTERNATE_SERVER, &alternate_server, NULL)==-1) { //error } else if(turn_addr && turn_port){ addr_to_string_no_port(&alternate_server, (u08bits*)turn_addr); *turn_port = (u16bits)addr_get_port(&alternate_server); } } TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "error %d (%s)\n", err_code,(char*)err_msg); if (err_code != 437) { allocate_finished = 1; current_reservation_token = 0; return -1; } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "trying allocate again %d...\n", err_code); sleep(1); reopen_socket = 1; } } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "unknown allocate response\n"); /* Try again ? */ } } else { perror("recv"); exit(-1); break; } } } } ////////////<<== allocate response received if(rare_event()) return 0; if(!allocate_finished) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot complete Allocation\n"); exit(-1); } allocate_rtcp = !allocate_rtcp; if (1) { af_cycle = 0; if(clnet_info->s_mobile_id[0]) { int fd = clnet_info->fd; SSL* ssl = clnet_info->ssl; int close_now = (int)(random()%2); if(close_now) { int close_socket = (int)(random()%2); if(ssl && !close_socket) { SSL_shutdown(ssl); SSL_FREE(ssl); fd = -1; } else if(fd>=0) { close(fd); fd = -1; ssl = NULL; } } app_ur_conn_info ci; ns_bcopy(clnet_info,&ci,sizeof(ci)); ci.fd = -1; ci.ssl = NULL; clnet_info->fd = -1; clnet_info->ssl = NULL; //Reopen: if(clnet_connect(addr_get_port(&(ci.remote_addr)), ci.rsaddr, (unsigned char*)ci.ifname, ci.lsaddr, clnet_verbose, clnet_info)<0) { exit(-1); } if(ssl) { SSL_shutdown(ssl); SSL_FREE(ssl); } else if(fd>=0) { close(fd); } } beg_refresh: if(af_cycle++>32) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot complete Refresh\n"); exit(-1); } //==>>refresh request, for an example only: { int refresh_sent = 0; stun_init_request(STUN_METHOD_REFRESH, &request_message); uint32_t lt = htonl(UCLIENT_SESSION_LIFETIME); stun_attr_add(&request_message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, 4); if(clnet_info->s_mobile_id[0]) { stun_attr_add(&request_message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id)); } if(dual_allocation && !mobility) { int t = ((u08bits)random())%3; if(t) { u08bits field[4]; field[0] = (t==1) ? (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4 : (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; field[1]=0; field[2]=0; field[3]=0; stun_attr_add(&request_message, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY, (const char*) field, 4); } } add_origin(&request_message); if(add_integrity(clnet_info, &request_message)<0) return -1; stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!refresh_sent) { int len = send_buffer(clnet_info, &request_message, 0,0); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "refresh sent\n"); } refresh_sent = 1; if(clnet_info->s_mobile_id[0]) { usleep(10000); send_buffer(clnet_info, &request_message, 0,0); } } else { perror("send"); exit(1); } } } if(not_rare_event()) return 0; ////////refresh response==>> { int refresh_received = 0; while (!refresh_received) { int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if(clnet_info->s_mobile_id[0]) { len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); } if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "refresh response received: \n"); } response_message.len = len; int err_code = 0; u08bits err_msg[129]; if (stun_is_success_response(&response_message)) { read_mobility_ticket(clnet_info, &response_message); refresh_received = 1; if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); } } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { goto beg_refresh; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { refresh_received = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "error %d (%s)\n", err_code,(char*)err_msg); return -1; } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "unknown refresh response\n"); /* Try again ? */ } } else { perror("recv"); exit(-1); break; } } } } return 0; }
static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, app_tcp_conn_info *atc, int errorOK) { stun_buffer request_message, response_message; beg_cb: { int cb_sent = 0; u32bits cid = atc->cid; stun_init_request(STUN_METHOD_CONNECTION_BIND, &request_message); stun_attr_add(&request_message, STUN_ATTRIBUTE_CONNECTION_ID, (const s08bits*)&cid,4); add_origin(&request_message); if(add_integrity(clnet_info, &request_message)<0) return -1; stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!cb_sent) { int len = send_buffer(clnet_info, &request_message, 1, atc); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "connection bind sent\n"); } cb_sent = 1; } else { if(errorOK) return 0; perror("send"); exit(1); } } } ////////////<<==connection bind send if(not_rare_event()) return 0; ////////connection bind response==>> { int cb_received = 0; while (!cb_received) { int len = recv_buffer(clnet_info, &response_message, 1, 1, atc, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "connect bind response received: \n"); } int err_code = 0; u08bits err_msg[129]; if (stun_is_success_response(&response_message)) { if(clnet_info->nonce[0]) { if(check_integrity(clnet_info, &response_message)<0) return -1; } if(stun_get_method(&response_message)!=STUN_METHOD_CONNECTION_BIND) continue; cb_received = 1; if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); } atc->tcp_data_bound = 1; } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { goto beg_cb; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { cb_received = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "connection bind error %d (%s)\n", err_code,(char*)err_msg); return -1; } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "unknown connection bind response\n"); /* Try again ? */ } } else { if(errorOK) return 0; perror("recv"); exit(-1); } } } return 0; }
void client(int clinx, char *name, long id, int inx) { int ferr; int lerr; bool ok; int match; Util_AA<int> msgid(MAX_SENDS); Util_AA<char> recv_buffer(MAX_SENDS * BUFSIZ); Util_AA<short> recv_buffer3(MAX_SENDS * BUFSIZ); RT results; int send; Util_AA<char> send_buffer(MAX_SENDS * BUFSIZ); Util_AA<short> send_buffer2(MAX_SENDS * BUFSIZ); int send_len; MS_SRE_LDONE sre_ldone; for (send = 0; send < MAX_SENDS; send++) { sprintf(&send_buffer.ip_v[send * BUFSIZ], "hello, greetings from %s, name=%s, id=%ld, inx=%d, send=%d", my_name, name, id, inx, send); while (clinx >= 0) { strcat(&send_buffer.ip_v[send * BUFSIZ], "!"); clinx--; } send_len = (int) strlen(&send_buffer.ip_v[send * BUFSIZ]) + 1; ferr = XMSG_LINK_(TPT_REF(phandle), // phandle &msgid.ip_v[send], // msgid &send_buffer2.ip_v[send * BUFSIZ], // reqctrl (ushort) (inx & 1), // reqctrlsize &recv_buffer3.ip_v[send * BUFSIZ], // replyctrl 1, // replyctrlmax &send_buffer.ip_v[send * BUFSIZ], // reqdata (ushort) send_len, // reqdatasize &recv_buffer.ip_v[send * BUFSIZ], // replydata BUFSIZ, // replydatamax (SB_Tag_Type) // linkertag &send_buffer.ip_v[send * BUFSIZ], 0, // pri 0, // xmitclass XMSG_LINK_LDONEQ); // linkopts util_check("XMSG_LINK_", ferr); } for (send = 0; send < MAX_SENDS;) { lerr = XWAIT(LDONE, -1); TEST_CHK_WAITIGNORE(lerr); for (;;) { lerr = XMSG_LISTEN_((short *) &sre_ldone, // sre 0, // listenopts 0); // listenertag if (lerr == XSRETYPE_NOWORK) break; send++; assert(lerr == XSRETYPE_LDONE); ok = false; for (match = 0; match < MAX_SENDS; match++) { if (sre_ldone.sre_linkTag == (SB_Tag_Type) &send_buffer.ip_v[match * BUFSIZ]) { ok = true; break; } } assert(ok); ferr = XMSG_BREAK_(msgid.ip_v[match], results.u.s, TPT_REF(phandle)); util_check("XMSG_BREAK_", ferr); assert(results.u.t.ctrl_size == (uint) (inx & 1)); assert(results.u.t.data_size > (strlen(&send_buffer.ip_v[match * BUFSIZ]) + 14)); assert(results.u.t.errm == RT_DATA_RCVD); // data printf("%s\n", &recv_buffer.ip_v[match * BUFSIZ]); } } }
void *client_thr(void *arg) { Util_AA<char> event_data(MS_MON_MAX_SYNC_DATA); int event_len; int ferr; int inx; int msgid; Util_AA<char> recv_buffer(BUFSIZ); Util_AA<short> recv_buffer3(BUFSIZ); RT results; Util_AA<char> send_buffer(BUFSIZ); Util_AA<short> send_buffer2(BUFSIZ); int send_len; long t_elapsed; struct timeval t_start; struct timeval t_stop; int whoami = inxc++; arg = arg; // touch if (event) { ferr = msg_mon_event_wait(1, &event_len, &event_data); TEST_CHK_FEOK(ferr); } util_time_timer_start(&t_start); for (inx = 0; inx < loop; inx++) { if (txrate) { if ((inx % 100) == 0) { util_time_timer_stop(&t_stop); t_elapsed = (t_stop.tv_sec * 1000000 + t_stop.tv_usec) - (t_start.tv_sec * 1000000 + t_start.tv_usec); t_elapsed = t_elapsed / 1000; if (inx == 0) printf("%s: c-%d\n", name, whoami); else printf("%s: c-%d, inx=%d, msg/ms=%ld\n", name, whoami, inx, t_elapsed / inx); } } else if (mq) { if ((inx % 100) == 0) printf("%s: c-%d, inx=%d\n", name, whoami, inx); } else if (!quiet) printf("c-%d, inx=%d\n", whoami, inx); fflush(stdout); sprintf(&send_buffer, "hello, greetings from %s-%d, inx=%d", my_name, whoami, inx); send_len = (int) strlen(&send_buffer) + 1; if (verbose) printf("c-%d: sending %s\n", whoami, &send_buffer); ferr = XMSG_LINK_(TPT_REF(phandle), // phandle &msgid, // msgid &send_buffer2, // reqctrl (ushort) (inx & 1), // reqctrlsize &recv_buffer3, // replyctrl (ushort) 1, // replyctrlmax &send_buffer, // reqdata (ushort) send_len, // reqdatasize &recv_buffer, // replydata (ushort) BUFSIZ, // replydatamax 0, // linkertag 0, // pri 0, // xmitclass 0); // linkopts if (!abortserver) util_check("XMSG_LINK_", ferr); ferr = XMSG_BREAK_(msgid, results.u.s, TPT_REF(phandle)); if (!abortserver) util_check("XMSG_BREAK_", ferr); if (!abortserver) { if (verbose) printf("c-%d: received %s\n", whoami, &recv_buffer); assert(results.u.t.ctrl_size == (uint) (inx & 1)); assert(results.u.t.data_size == 100); assert(results.u.t.errm == RT_DATA_RCVD); // data if (inx == (loop - 1)) { if (maxcp > 1) printf("%s: %s\n", name, &recv_buffer); else printf("%s\n", &recv_buffer); } } } return NULL; }
void handle_rx(unsigned char rx_data, unsigned char rx_er, unsigned char rx_dv) { if (!rx_dv | rx_er) { rx_status <= STATUS_READY; } else { switch (rx_status) { case STATUS_READY: { if (rx_data == 0x55) rx_status = STATUS_PREAMBLE_0; break; } case STATUS_PREAMBLE_0: { if (rx_data == 0x55) rx_status = STATUS_PREAMBLE_1; else rx_status = STATUS_READY; break; } case STATUS_PREAMBLE_1: { if (rx_data == 0x55) rx_status = STATUS_PREAMBLE_2; else rx_status = STATUS_READY; break; } case STATUS_PREAMBLE_2: { if (rx_data == 0x55) rx_status = STATUS_PREAMBLE_3; else rx_status = STATUS_READY; break; } case STATUS_PREAMBLE_3: { if (rx_data == 0x55) rx_status = STATUS_PREAMBLE_4; else rx_status = STATUS_READY; break; } case STATUS_PREAMBLE_4: { if (rx_data == 0x55) rx_status = STATUS_PREAMBLE_5; else rx_status = STATUS_READY; break; } case STATUS_PREAMBLE_5: { if (rx_data == 0x55) rx_status = STATUS_PREAMBLE_6; else rx_status = STATUS_READY; break; } case STATUS_PREAMBLE_6: { if (rx_data == 0x55) rx_status = STATUS_SDF; else rx_status = STATUS_READY; break; } case STATUS_SDF: { if (rx_data == 0xd5) { rx_status = STATUS_DATA; rx_crc32 = 0; recv_buffer_next(); } else rx_status = STATUS_READY; break; } STATUS_DATA: { if (rx_current_adr < PACKET_SIZE) { if (rx_crc32 != 0xC704DD7B) { recv_buffer(rx_current_adr, rx_data); rx_crc32 = next_crc32_d8(rx_data, rx_crc32); rx_current_adr++; } else rx_status = STATUS_DONE; } else { rx_status = STATUS_READY; } break; } case STATUS_DONE: { rx_status = STATUS_READY; // Remove last 4 bytes recv_buffer_fix(); break; } default: { rx_status = STATUS_READY; break; } } } }
static int handle_request(struct connreq *conn) { int rc = 0; int i = 0; show_msg(MSGDEBUG, "Beginning handle loop for socket %d\n", conn->sockid); while ((rc == 0) && (conn->state != FAILED) && (conn->state != DONE) && (i++ < 20)) { show_msg(MSGDEBUG, "In request handle loop for socket %d, " "current state of request is %d\n", conn->sockid, conn->state); switch(conn->state) { case UNSTARTED: case CONNECTING: rc = connect_server(conn); break; case CONNECTED: rc = send_socks_request(conn); break; case SENDING: rc = send_buffer(conn); break; case RECEIVING: rc = recv_buffer(conn); break; case SENTV4REQ: show_msg(MSGDEBUG, "Receiving reply to SOCKS V4 connect request\n"); conn->datalen = sizeof(struct sockrep); conn->datadone = 0; conn->state = RECEIVING; conn->nextstate = GOTV4REQ; break; case GOTV4REQ: rc = read_socksv4_req(conn); break; case SENTV5METHOD: show_msg(MSGDEBUG, "Receiving reply to SOCKS V5 method negotiation\n"); conn->datalen = 2; conn->datadone = 0; conn->state = RECEIVING; conn->nextstate = GOTV5METHOD; break; case GOTV5METHOD: rc = read_socksv5_method(conn); break; case SENTV5AUTH: show_msg(MSGDEBUG, "Receiving reply to SOCKS V5 authentication negotiation\n"); conn->datalen = 2; conn->datadone = 0; conn->state = RECEIVING; conn->nextstate = GOTV5AUTH; break; case GOTV5AUTH: rc = read_socksv5_auth(conn); break; case SENTV5CONNECT: show_msg(MSGDEBUG, "Receiving reply to SOCKS V5 connect request\n"); conn->datalen = 10; conn->datadone = 0; conn->state = RECEIVING; conn->nextstate = GOTV5CONNECT; break; case GOTV5CONNECT: rc = read_socksv5_connect(conn); break; } conn->err = errno; } if (i == 20) show_msg(MSGERR, "Ooops, state loop while handling request %d\n", conn->sockid); show_msg(MSGDEBUG, "Handle loop completed for socket %d in state %d, " "returning %d\n", conn->sockid, conn->state, rc); return(rc); }
static ssize_t recv_buffer(int fd, int fds[3]) { struct iovec iov = { .iov_base = buffer, .iov_len = sizeof(buffer) }; struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, .msg_controllen = CMSG_SPACE(3 * sizeof(int)), }; msg.msg_control = alloca(msg.msg_controllen); memset(msg.msg_control, 0, msg.msg_controllen); ssize_t recvd; NO_EINTR(recvd, recvmsg(fd, &msg, 0)); if (recvd == -1) { perror("recvmsg"); return -1; } if (recvd < 4) { ssize_t recvd_; do { NO_EINTR(recvd_, recv(fd, buffer + recvd, sizeof(buffer) - recvd, 0)); if (recvd_ > 0) recvd += recvd_; } while (recvd_ > 0 && recvd < 4); } size_t target = -1; if (recvd > 4) { target = unbyte(buffer[0],0) | unbyte(buffer[1],1) | unbyte(buffer[2],2) | unbyte(buffer[3],3); if (recvd < target) { ssize_t recvd_; do { NO_EINTR(recvd_, recv(fd, buffer + recvd, sizeof(buffer) - recvd, 0)); if (recvd_ > 0) recvd += recvd_; } while (recvd_ > 0 && recvd < target); } } struct cmsghdr *cm = CMSG_FIRSTHDR(&msg); int *fds0 = (int*)CMSG_DATA(cm); int nfds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int); /* Check malformed packet */ if (nfds != 3 || recvd != target || buffer[recvd-1] != '\0') { int i; for (i = 0; i < nfds; ++i) close(fds0[i]); return -1; } fds[0] = fds0[0]; fds[1] = fds0[1]; fds[2] = fds0[2]; return recvd; } value ml_merlin_server_setup(value path, value strfd) { CAMLparam2(path, strfd); CAMLlocal2(payload, ret); char *endptr = NULL; int fd = strtol(String_val(strfd), &endptr, 0); if (endptr && *endptr == '\0') { /* (path, fd) */ payload = caml_alloc(2, 0); Store_field(payload, 0, path); Store_field(payload, 1, Val_int(fd)); /* Some payload */ ret = caml_alloc(1, 0); Store_field(ret, 0, payload); } else { fprintf(stderr, "ml_merlin_server_setup(\"%s\",\"%s\"): invalid argument\n", String_val(path), String_val(strfd)); unlink(String_val(path)); /* None */ ret = Val_unit; } CAMLreturn(ret); } value ml_merlin_server_accept(value server, value val_timeout) { CAMLparam2(server, val_timeout); CAMLlocal4(ret, client, args, context); // Compute timeout double timeout = Double_val(val_timeout); struct timeval tv; tv.tv_sec = timeout; tv.tv_usec = (timeout - tv.tv_sec) * 1000000; // Select on server int serverfd = Int_val(Field(server, 1)); int selectres; fd_set readset; do { FD_ZERO(&readset); FD_SET(serverfd, &readset); selectres = select(serverfd + 1, &readset, NULL, NULL, &tv); } while (selectres == -1 && errno == EINTR); int fds[3], clientfd; ssize_t len = -1; if (selectres > 0) { NO_EINTR(clientfd, accept(serverfd, NULL, NULL)); len = recv_buffer(clientfd, fds); } if (len == -1) ret = Val_unit; /* None */ else { context = caml_alloc(4, 0); /* (clientfd, stdin, stdout, stderr) */ Store_field(context, 0, Val_int(clientfd)); Store_field(context, 1, Val_int(fds[0])); Store_field(context, 2, Val_int(fds[1])); Store_field(context, 3, Val_int(fds[2])); ssize_t i, j; int argc = 0; for (i = 4; i < len; ++i) if (buffer[i] == '\0') argc += 1; args = caml_alloc(argc, 0); argc = 0; for (i = 4, j = 4; i < len; ++i) { if (buffer[i] == '\0') { Store_field(args, argc, caml_copy_string((const char *)&buffer[j])); j = i + 1; argc += 1; } } client = caml_alloc(2, 0); /* (context, args) */ Store_field(client, 0, context); Store_field(client, 1, args); ret = caml_alloc(1, 0); /* Some client */ Store_field(ret, 0, client); } CAMLreturn(ret); }