예제 #1
0
/**
 * 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;
}
예제 #2
0
    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
예제 #3
0
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
		}
	}
}
예제 #4
0
    /// 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;
    }
예제 #5
0
/* 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;
}
예제 #6
0
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);
}
예제 #7
0
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++;
      }
    }
  }
}
예제 #8
0
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
    }
}
예제 #9
0
    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
    }
예제 #10
0
    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
예제 #11
0
    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
예제 #12
0
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;
}
예제 #13
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;
}
예제 #14
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*) &lt, 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;
}
예제 #15
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;
}
예제 #16
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]);
        }
    }
}
예제 #17
0
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;
}
예제 #18
0
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;
			}
		}
	}
}
예제 #19
0
파일: tsocks.c 프로젝트: TamasSzerb/tsocks
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);
}
예제 #20
0
파일: os_ipc_stub.c 프로젝트: bluddy/merlin
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);
}