//////////////////////////////////////////////////////////////////////
// Datagram 객체로부터 데이타를 읽어서 패킷을 초기화한다.
//////////////////////////////////////////////////////////////////////
void LGIncomingConnectionOK::read (Datagram & iDatagram ) 
	 throw(ProtocolException , Error )
{
	__BEGIN_TRY

	//--------------------------------------------------
	// read Player ID
	//--------------------------------------------------
	BYTE szPlayerID;

	iDatagram.read(szPlayerID);

	if (szPlayerID == 0 )
		throw InvalidProtocolException("szPlayerID == 0");

	if (szPlayerID > 20 )
		throw InvalidProtocolException("too long playerID size");

	iDatagram.read(m_PlayerID , szPlayerID);

	//--------------------------------------------------
	// read TCP Port
	//--------------------------------------------------
	iDatagram.read(m_TCPPort);

	//--------------------------------------------------
	// read Auth Key
	//--------------------------------------------------
	iDatagram.read(m_Key);

	__END_CATCH
}
Example #2
0
void    Channel::AddHint (Datagram& dgram) {

    tint plan_for = max(TINT_SEC,rtt_avg_*4);

    tint timed_out = NOW - plan_for*2;
    while ( !hint_out_.empty() && hint_out_.front().time < timed_out ) {
        hint_out_size_ -= hint_out_.front().bin.width();
        hint_out_.pop_front();
    }

    int plan_pck = max ( (tint)1, plan_for / dip_avg_ );

    if ( hint_out_size_ < plan_pck ) {

        int diff = plan_pck - hint_out_size_; // TODO: aggregate
        bin64_t hint = transfer().picker().Pick(ack_in_,diff,NOW+plan_for*2);

        if (hint!=bin64_t::NONE) {
            dgram.Push8(SWIFT_HINT);
            dgram.Push32(hint);
            dprintf("%s #%u +hint %s [%lli]\n",tintstr(),id_,hint.str(),hint_out_size_);
            hint_out_.push_back(hint);
            hint_out_size_ += hint.width();
        } else
            dprintf("%s #%u Xhint\n",tintstr(),id_);

    }
}
Example #3
0
//////////////////////////////////////////////////////////////////////
//
// receive datagram from peer
//
// 만약에 이 클래스를 blocking 으로 사용한다면, (즉 select 기반으로)
// 아마도 nReceived 가 0 이하인 경우는 없으리라고 판단된다.
//
//////////////////////////////////////////////////////////////////////
Datagram * DatagramSocket::receive ()
	throw(ConnectException , Error )
{
	__BEGIN_TRY 

	Datagram * pDatagram = NULL;

	SOCKADDR_IN SockAddr;
	uint _szSOCKADDR_IN = szSOCKADDR_IN;

	// 내부 버퍼에다가 복사해둔다.
	int nReceived = SocketAPI::recvfrom_ex(m_SocketID , m_Buffer , DATAGRAM_SOCKET_BUFFER_LEN , 0 , (SOCKADDR*)&SockAddr , &_szSOCKADDR_IN);

	if (nReceived > 0 ) {

		pDatagram = new Datagram();
		pDatagram->setData(m_Buffer , nReceived);
		pDatagram->setAddress(&SockAddr);

	}

	return pDatagram;

	__END_CATCH
}
Example #4
0
//////////////////////////////////////////////////////////////////////
// Datagram 객체로부터 데이타를 읽어서 패킷을 초기화한다.
//////////////////////////////////////////////////////////////////////
void RCSay::read (Datagram & iDatagram ) 
	 throw(ProtocolException , Error )
{
	__BEGIN_TRY

	// Name
	BYTE szName;

	iDatagram.read(szName);

	if (szName == 0 )
		throw InvalidProtocolException("szName == 0");

	if (szName > 20 )
		throw InvalidProtocolException("too long Name length");

	iDatagram.read(m_Name , szName);

	// message
	BYTE szMessage;

	iDatagram.read(szMessage);

	if (szMessage == 0 )
		throw InvalidProtocolException("szMessage == 0");

	if (szMessage > 128 )
		throw InvalidProtocolException("too long message length");

	iDatagram.read(m_Message , szMessage);

	__END_CATCH
}
void GameDataReceiverThread::run()
{
    const size_t MAX_PACKET_SIZE = 0x1000;

    ScopedLock<Mutex> lock(d->mutex);

    try
    {
        for (;;)
        {
            Datagram dg;
            {
                ReverseScopedLock<Mutex> unlock(d->mutex);

                dg = d->socket->receive(MAX_PACKET_SIZE);
            }

            BufferStream bs(dg.getData());

            framenum_t frameNum = 0;
            FrameData frameData;
            bs >> frameNum >> frameData;

            // Notify
            d->eventLoop->postEvent(new GameDataEvent(frameNum, frameData));
        }
    }
    catch (const Exception& e)
    {
        PERROR << e;
    }
}
Example #6
0
//////////////////////////////////////////////////////////////////////
// Datagram 객체로 패킷의 바이너리 이미지를 보낸다.
//////////////////////////////////////////////////////////////////////
void RCSay::write (Datagram & oDatagram ) const 
     throw(ProtocolException , Error )
{
	__BEGIN_TRY

	// Name
	BYTE szName = m_Name.size();

	if (szName == 0 )
		throw InvalidProtocolException("szName == 0");

	if (szName > 20 )
		throw InvalidProtocolException("too long Name length");

	oDatagram.write(szName);
	oDatagram.write(m_Name);

	// message
	BYTE szMessage = m_Message.size();

	if (szMessage == 0 )
		throw InvalidProtocolException("szMessage == 0");

	if (szMessage > 128 )
		throw InvalidProtocolException("too long message length");

	oDatagram.write(szMessage);
	oDatagram.write(m_Message);

	__END_CATCH
}
Example #7
0
void    Channel::Recv (Datagram& dgram) {
    dprintf("%s #%u recvd %ib\n",tintstr(),id_,dgram.size()+4);
    dgrams_rcvd_++;
    if (last_send_time_ && rtt_avg_==TINT_SEC && dev_avg_==0) {
        rtt_avg_ = NOW - last_send_time_;
        dev_avg_ = rtt_avg_;
        dip_avg_ = rtt_avg_;
        dprintf("%s #%u sendctrl rtt init %lli\n",tintstr(),id_,rtt_avg_);
    }
    bin64_t data = dgram.size() ? bin64_t::NONE : bin64_t::ALL;
    while (dgram.size()) {
        uint8_t type = dgram.Pull8();
        switch (type) {
            case SWIFT_HANDSHAKE: OnHandshake(dgram); break;
            case SWIFT_DATA:      data=OnData(dgram); break;
            case SWIFT_HAVE:      OnHave(dgram); break;
            case SWIFT_ACK:       OnAck(dgram); break;
            case SWIFT_HASH:      OnHash(dgram); break;
            case SWIFT_HINT:      OnHint(dgram); break;
            case SWIFT_PEX_ADD:   OnPex(dgram); break;
            default:
                eprintf("%s #%u ?msg id unknown %i\n",tintstr(),id_,(int)type);
                return;
        }
    }
    last_recv_time_ = NOW;
    sent_since_recv_ = 0;
    Reschedule();
}
Example #8
0
    /* apparently passes data buffer to lower layer, what is return value? */
    int send_down(Datagram& dg, const ProtoDownMeta& down_meta)
    {
        if (down_context_.empty() == true)
        {
            log_warn << this << " down context(s) not set";
            return ENOTCONN;
        }

        int    ret         = 0;
        for (CtxList::iterator i = down_context_.begin();
             i != down_context_.end(); ++i)
        {
            const size_t hdr_offset(dg.header_offset());
            int err = (*i)->handle_down(dg, down_meta);
            // Verify that lower layer rolls back any modifications to
            // header
            if (hdr_offset != dg.header_offset())
            {
                gu_throw_fatal;
            }
            if (err != 0)
            {
                ret = err;
            }
        }
        return ret;
    }
Example #9
0
bool CanonDriver::requestCurrentPos()
{
	Datagram dgm;
	dgm.reset();
	dgm.setId(0x33);
	dgm.setStatus(0x8000);

	cm.addToReceptionField(0x33);
	if (!cm.send(dgm)) {
		if (verbose) {
			printf("%s: Can't send datagram: ",__FUNCTION__);
			dgm.print(stdout);
			printf("\n");
		}
		goto cleanup;
	}

	if (!cm.wait(0x33,dgm)) goto cleanup;
	cm.removeFromReceptionField(0x33);
	return interpreteDatagram33(dgm);

cleanup:
	if (verbose)
		printf("requestCurrentPos failed\n");
	cm.removeFromReceptionField(0x33);
	return false;
}
//////////////////////////////////////////////////////////////////////
// Datagram 객체로 패킷의 바이너리 이미지를 보낸다.
//////////////////////////////////////////////////////////////////////
void LGIncomingConnectionOK::write (Datagram & oDatagram ) const 
     throw(ProtocolException , Error )
{
	__BEGIN_TRY

	//--------------------------------------------------
	// write Player ID
	//--------------------------------------------------
	BYTE szPlayerID = m_PlayerID.size();

	if (szPlayerID == 0 )
		throw InvalidProtocolException("szPlayerID == 0");

	if (szPlayerID > 20 )
		throw InvalidProtocolException("too long playerID size");

	oDatagram.write(szPlayerID);

	oDatagram.write(m_PlayerID);

	//--------------------------------------------------
	// write TCP Port
	//--------------------------------------------------
	oDatagram.write(m_TCPPort);

	//--------------------------------------------------
	// write auth Key
	//--------------------------------------------------
	oDatagram.write(m_Key);

	__END_CATCH
}
Example #11
0
void    Channel::AddPeakHashes (Datagram& dgram) {
    for(int i=0; i<file().peak_count(); i++) {
        bin64_t peak = file().peak(i);
        dgram.Push8(SWIFT_HASH);
        dgram.Push32((uint32_t)peak);
        dgram.PushHash(file().peak_hash(i));
        dprintf("%s #%u +phash %s\n",tintstr(),id_,peak.str());
    }
}
Example #12
0
void    Channel::AddUncleHashes (Datagram& dgram, bin64_t pos) {
    bin64_t peak = file().peak_for(pos);
    while (pos!=peak && ((NOW&3)==3 || !data_out_cap_.within(pos.parent())) &&
            ack_in_.get(pos.parent())==binmap_t::EMPTY  ) {
        bin64_t uncle = pos.sibling();
        dgram.Push8(SWIFT_HASH);
        dgram.Push32((uint32_t)uncle);
        dgram.PushHash( file().hash(uncle) );
        dprintf("%s #%u +hash %s\n",tintstr(),id_,uncle.str());
        pos = pos.parent();
    }
}
Example #13
0
void    Channel::OnAck (Datagram& dgram) {
    bin64_t ackd_pos = dgram.Pull32();
    tint peer_time = dgram.Pull64(); // FIXME 32
    // FIXME FIXME: wrap around here
    if (ackd_pos==bin64_t::NONE)
        return; // likely, brocken packet / insufficient hashes
    if (file().size() && ackd_pos.base_offset()>=file().packet_size()) {
        eprintf("invalid ack: %s\n",ackd_pos.str());
        return;
    }
    ack_in_.set(ackd_pos);
    int di = 0, ri = 0;
    // find an entry for the send (data out) event
    while (  di<data_out_.size() && ( data_out_[di]==tintbin() ||
           !data_out_[di].bin.within(ackd_pos) )  )
        di++;
    // FUTURE: delayed acks
    // rule out retransmits
    while (  ri<data_out_tmo_.size() && !data_out_tmo_[ri].bin.within(ackd_pos) )
        ri++;
    dprintf("%s #%u %cack %s %lli\n",tintstr(),id_,
            di==data_out_.size()?'?':'-',ackd_pos.str(),peer_time);
    if (di!=data_out_.size() && ri==data_out_tmo_.size()) { // not a retransmit
            // round trip time calculations
        tint rtt = NOW-data_out_[di].time;
        rtt_avg_ = (rtt_avg_*7 + rtt) >> 3;
        dev_avg_ = ( dev_avg_*3 + abs(rtt-rtt_avg_) ) >> 2;
        assert(data_out_[di].time!=TINT_NEVER);
            // one-way delay calculations
        tint owd = peer_time - data_out_[di].time;
        owd_cur_bin_ = 0;//(owd_cur_bin_+1) & 3;
        owd_current_[owd_cur_bin_] = owd;
        if ( owd_min_bin_start_+TINT_SEC*30 < NOW ) {
            owd_min_bin_start_ = NOW;
            owd_min_bin_ = (owd_min_bin_+1) & 3;
            owd_min_bins_[owd_min_bin_] = TINT_NEVER;
        }
        if (owd_min_bins_[owd_min_bin_]>owd)
            owd_min_bins_[owd_min_bin_] = owd;
        dprintf("%s #%u sendctrl rtt %lli dev %lli based on %s\n",
                tintstr(),id_,rtt_avg_,dev_avg_,data_out_[di].bin.str());
        ack_rcvd_recent_++;
        // early loss detection by packet reordering
        for (int re=0; re<di-MAX_REORDERING; re++) {
            if (data_out_[re]==tintbin())
                continue;
            ack_not_rcvd_recent_++;
            data_out_tmo_.push_back(data_out_[re].bin);
            dprintf("%s #%u Rdata %s\n",tintstr(),id_,data_out_.front().bin.str());
            data_out_cap_ = bin64_t::ALL;
            data_out_[re] = tintbin();
        }
    }
Example #14
0
bool CanonDriver::getFocusMode(FocusMode * fm, ManualFocusMode * mfm)
{
	Datagram dgm;
	if (!sendRequestAndWait(0x40,0x8000,dgm))
		return false;
	*fm = (FocusMode)(dgm.bdata()[0]);
	if (*fm == FMManual) {
		if (!sendRequestAndWait(0x43,0x8000,dgm))
			return false;
		*mfm = (ManualFocusMode)(dgm.bdata()[0]);
	}
	return true;
}
Example #15
0
void    Channel::AddAck (Datagram& dgram) {
    if (data_in_==tintbin())
        return;
    dgram.Push8(SWIFT_ACK);
    dgram.Push32(data_in_.bin.to32()); // FIXME not cover
    dgram.Push64(data_in_.time); // FIXME 32
    have_out_.set(data_in_.bin);
    dprintf("%s #%u +ack %s %s\n",
        tintstr(),id_,data_in_.bin.str(),tintstr(data_in_.time));
    if (data_in_.bin.layer()>2)
        data_in_dbl_ = data_in_.bin;
    data_in_ = tintbin();
}
Example #16
0
void    Channel::AddHandshake (Datagram& dgram) {
    if (!peer_channel_id_) { // initiating
        dgram.Push8(SWIFT_HASH);
        dgram.Push32(bin64_t::ALL32);
        dgram.PushHash(file().root_hash());
        dprintf("%s #%u +hash ALL %s\n",
                tintstr(),id_,file().root_hash().hex().c_str());
    }
    dgram.Push8(SWIFT_HANDSHAKE);
    int encoded = EncodeID(id_);
    dgram.Push32(encoded);
    dprintf("%s #%u +hs %x\n",tintstr(),id_,encoded);
    have_out_.clear();
    AddHave(dgram);
}
Example #17
0
Datagram* IpRouter::readPacket() {
    // If the file stream is at the end of the file, all packets have been read. Return NULL.
    if(packetsFS.peek() == EOF) {
        packetsFS.close();
        return NULL;
    }

    // Create a packet on the Heap so it can exist longer than the scope of this function
    Datagram* packet = new Datagram;

    // Read packet data into object
    packet->read(packetsFS);

    return packet;
}
Example #18
0
bool CanonDriver::getSpeeds(unsigned short * pan, 
		unsigned short * tilt, unsigned short * zoom)
{
	Datagram dgm;
	if (!sendRequestAndWait(0x3B,0x8000,dgm))
		return false;
	const unsigned char * data = dgm.bdata();
	*pan = data[0];
	*pan = (*pan << 8) | data[1];
	*tilt = data[2];
	*tilt = (*tilt << 8) | data[3];
	*zoom = data[4];
	*zoom = (*zoom << 8) | data[5];
	return true;
}
Example #19
0
void Client::log_event(const std::list<std::string> &event)
{
	Datagram dg;

	std::stringstream ss;
	ss << "Client:" << m_allocated_channel;
	dg.add_string(ss.str());

	for(auto it = event.begin(); it != event.end(); ++it)
	{
		dg.add_string(*it);
	}

	g_eventsender.send(dg);
}
Example #20
0
int gcomm::PC::handle_down(Datagram& wb, const ProtoDownMeta& dm)
{
    if (wb.len() == 0)
    {
        gu_throw_error(EMSGSIZE);
    }
    return send_down(wb, dm);
}
Example #21
0
void    Channel::AddHave (Datagram& dgram) {
    if (data_in_dbl_!=bin64_t::NONE) { // TODO: do redundancy better
        dgram.Push8(SWIFT_HAVE);
        dgram.Push32(data_in_dbl_.to32());
        data_in_dbl_=bin64_t::NONE;
    }
    for(int count=0; count<4; count++) {
        bin64_t ack = file().ack_out().find_filtered // FIXME: do rotating queue
            (have_out_, bin64_t::ALL, binmap_t::FILLED);
        if (ack==bin64_t::NONE)
            break;
        ack = file().ack_out().cover(ack);
        have_out_.set(ack);
        dgram.Push8(SWIFT_HAVE);
        dgram.Push32(ack.to32());
        dprintf("%s #%u +have %s\n",tintstr(),id_,ack.str());
    }
}
Example #22
0
bool CanonDriver::getAutoExposure(bool * autoexp, AutoExposureMode * aem)
{
	Datagram dgm;
	if (!sendRequestAndWait(0x82,0x8000,dgm))
		return false;
	//dgm.print();
	*autoexp = (dgm.bdata()[0] == 0x00);
	if (!*autoexp) {
		*aem = AXPundef;
		return true;
	}
	if (!sendRequestAndWait(0x87,0x8000,dgm))
		return false;
	unsigned short us = dgm.bdata()[0];
	us = (us << 8) | dgm.bdata()[1];
	*aem = (AutoExposureMode)(us);
	//dgm.print();
	return true;
}
Example #23
0
void IRC_Server::receive_datagram(Datagram datagram, Host & host)
{
	std::smatch result;
    std::string datagram_id = host.get_name();
	std::string message = datagram.get_message();
    if (std::regex_search(message, result, std::regex("^CONNECT$"))
    	|| std::regex_search(message, result, std::regex("^USER [\\w\\d]+$"))
    	|| std::regex_search(message, result, std::regex("^QUIT$"))
    	)
    {
        datagram_id = datagram_id + "." + std::to_string(host.get_count_and_add());
    	std::string source_ip = host.ip_;
        int source_port = IRC_SERVER_PORT;
		std::string destination_ip = datagram.get_source_ip();
        int destination_port = datagram.get_source_port();
		std::string content = ":" + host.get_name() + " " + message;
    	host.add_to_send_datagram_queue(Datagram(source_ip, destination_ip, new UDP_Segment(source_port, destination_port, content), datagram_id));
    }
}
Example #24
0
void IpRouter::getPackets() {
    Datagram* packet;
    int counter = 1;
    // Read in every packet until the end of the file
    while((packet = readPacket())) {

        // Check for checksum and TTL errors
        if( !packet->compareChecksum() ) {
            packet->setError("Checksum is incorrect");
        } else if( !packet->decrementTTL()) {
            packet->setError("TTL becomes 0");
        } 

        // Set packet number
        packet->num = counter;

        // Store packet in vector
        datagrams.push_back(packet);
        ++counter;
    }
}
int gcomm::AsioUdpSocket::send(const Datagram& dg)
{
    Critical<AsioProtonet> crit(net_);
    boost::array<asio::const_buffer, 3> cbs;
    NetHeader hdr(dg.len(), net_.version_);

    if (net_.checksum_ != NetHeader::CS_NONE)
    {
        hdr.set_crc32(crc32(net_.checksum_, dg), net_.checksum_);
    }

    gu::byte_t buf[NetHeader::serial_size_];
    serialize(hdr, buf, sizeof(buf), 0);
    cbs[0] = asio::const_buffer(buf, sizeof(buf));
    cbs[1] = asio::const_buffer(dg.header() + dg.header_offset(),
                          dg.header_len());
    cbs[2] = asio::const_buffer(&dg.payload()[0], dg.payload().size());
    try
    {
        socket_.send_to(cbs, target_ep_);
    }
    catch (asio::system_error& err)
    {
        log_warn << "Error: " << err.what();
        return err.code().value();
    }
    return 0;
}
Example #26
0
bin64_t Channel::OnData (Datagram& dgram) {  // TODO: HAVE NONE for corrupted data
    bin64_t pos = dgram.Pull32();
    uint8_t *data;
    int length = dgram.Pull(&data,1024);
    bool ok = (pos==bin64_t::NONE) || file().OfferData(pos, (char*)data, length) ;
    dprintf("%s #%u %cdata %s\n",tintstr(),id_,ok?'-':'!',pos.str());
    data_in_ = tintbin(NOW,bin64_t::NONE);
    if (!ok)
        return bin64_t::NONE;
    for(int i=0; i<transfer().cb_installed; i++)
        transfer().callbacks[i](transfer().fd(),pos);  // FIXME FIXME FIXME
    data_in_.bin = pos;
    if (pos!=bin64_t::NONE) {
        if (last_data_in_time_) {
            tint dip = NOW - last_data_in_time_;
            dip_avg_ = ( dip_avg_*3 + dip ) >> 2;
        }
        last_data_in_time_ = NOW;
    }
    CleanHintOut(pos);
    return pos;
}
Example #27
0
void IRC_Client::receive_datagram(Datagram datagram, Host & host)
{
	int port = datagram.get_destination_port();
	if (port == DNS_CLIENT_PORT)
	{
		std::string dns_response = datagram.get_message();

		std::smatch result;
		std::regex_search(dns_response, result, std::regex("^(\\w+) A IN ([\\d\\.]+)$"));
		std::string response_hostname = result[1];
		std::string response_ip = result[2];

		for (std::string cmd : commands_waiting_for_dns)
		{
			std::smatch result2;
			std::regex_search(cmd, result2, std::regex("^CONNECT ([\\w\\d]+)\\s+(\\d+)$"));
			if (result2[1] == response_hostname)
			{
				std::string new_command = std::string("CONNECT ") + response_ip + " " + std::string(result2[2]);
				process_command(new_command, host);
			}
		}
	}
	else if (port == IRC_CLIENT_PORT)
	{
		std::string irc_response = datagram.get_message();

		std::smatch result;
		if (std::regex_search(irc_response, result, std::regex("^:([\\w\\d]+) CONNECT$")))
		{
			connected_server_ip = datagram.get_source_ip();
			connected_server_port = datagram.get_source_port();
		}
		else if (!std::regex_search(irc_response, result, std::regex("^:([\\w\\d]+) USER .+$"))
			&& !std::regex_search(irc_response, result, std::regex("^:([\\w\\d]+) QUIT$")))
			printf("Datagrama desconhecido no %s\n", host.get_name().c_str());
	}
}
Example #28
0
bin64_t        Channel::AddData (Datagram& dgram) {

    if (!file().size()) // know nothing
        return bin64_t::NONE;

    bin64_t tosend = bin64_t::NONE;
    tint luft = send_interval_>>4; // may wake up a bit earlier
    if (data_out_.size()<cwnd_ &&
            last_data_out_time_+send_interval_<=NOW+luft) {
        tosend = DequeueHint();
        if (tosend==bin64_t::NONE) {
            dprintf("%s #%u sendctrl no idea what to send\n",tintstr(),id_);
            if (send_control_!=KEEP_ALIVE_CONTROL)
                SwitchSendControl(KEEP_ALIVE_CONTROL);
        }
    } else
        dprintf("%s #%u sendctrl wait cwnd %f data_out %i next %s\n",
                tintstr(),id_,cwnd_,data_out_.size(),tintstr(last_data_out_time_+NOW-send_interval_));

    if (tosend==bin64_t::NONE)// && (last_data_out_time_>NOW-TINT_SEC || data_out_.empty()))
        return bin64_t::NONE; // once in a while, empty data is sent just to check rtt FIXED

    if (ack_in_.is_empty() && file().size())
        AddPeakHashes(dgram);
    AddUncleHashes(dgram,tosend);
    if (!ack_in_.is_empty()) // TODO: cwnd_>1
        data_out_cap_ = tosend;

    if (dgram.size()>254) {
        dgram.Send(); // kind of fragmentation
        dgram.Push32(peer_channel_id_);
    }

    dgram.Push8(SWIFT_DATA);
    dgram.Push32(tosend.to32());

    uint8_t buf[1024];
    size_t r = pread(file().file_descriptor(),buf,1024,tosend.base_offset()<<10);
    // TODO: corrupted data, retries, caching
    if (r<0) {
        print_error("error on reading");
        return bin64_t::NONE;
    }
    assert(dgram.space()>=r+4+1);
    dgram.Push(buf,r);

    last_data_out_time_ = NOW;
    data_out_.push_back(tosend);
    dprintf("%s #%u +data %s\n",tintstr(),id_,tosend.str());

    return tosend;
}
//////////////////////////////////////////////////////////////////////
// Datagram 객체로부터 데이타를 읽어서 패킷을 초기화한다.
//////////////////////////////////////////////////////////////////////
void GLIncomingConnectionError::read (Datagram & iDatagram ) 
	 throw(ProtocolException , Error )
{
	__BEGIN_TRY

	//--------------------------------------------------
	//--------------------------------------------------
	BYTE szMessage;

	iDatagram.read(szMessage);

	if (szMessage == 0 ) 
		throw InvalidProtocolException("szMessage == 0");

	if (szMessage >= 128 )
		throw InvalidProtocolException("too large message length");

	iDatagram.read(m_Message , szMessage);


	//--------------------------------------------------
	//--------------------------------------------------
	BYTE szPlayerID;

	iDatagram.read(szPlayerID);

	if (szPlayerID == 0 ) 
		throw InvalidProtocolException("szPlayerID == 0");

	if (szPlayerID >= 128 )
		throw InvalidProtocolException("too large playerID length");

	iDatagram.read(m_PlayerID , szPlayerID);


	__END_CATCH
}
//////////////////////////////////////////////////////////////////////
// Datagram 객체로 패킷의 바이너리 이미지를 보낸다.
//////////////////////////////////////////////////////////////////////
void GLIncomingConnectionError::write (Datagram & oDatagram ) const 
     throw(ProtocolException , Error )
{
	__BEGIN_TRY

	//--------------------------------------------------
	//--------------------------------------------------
	BYTE szMessage = m_Message.size();

	if (szMessage == 0 ) 
		throw InvalidProtocolException("szMessage == 0");

	if (szMessage >= 128 )
		throw InvalidProtocolException("too large message length");

	oDatagram.write(szMessage);

	oDatagram.write(m_Message);


	//--------------------------------------------------
	//--------------------------------------------------
	BYTE szPlayerID = m_PlayerID.size();

	if (szPlayerID == 0 ) 
		throw InvalidProtocolException("szPlayerID == 0");

	if (szPlayerID >= 128 )
		throw InvalidProtocolException("too large playerID length");

	oDatagram.write(szPlayerID);

	oDatagram.write(m_PlayerID);

	__END_CATCH
}