////////////////////////////////////////////////////////////////////// // 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 }
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_); } }
////////////////////////////////////////////////////////////////////// // // 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 }
////////////////////////////////////////////////////////////////////// // 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; } }
////////////////////////////////////////////////////////////////////// // 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 }
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(); }
/* 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; }
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 }
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()); } }
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(); } }
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(); } }
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; }
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(); }
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); }
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; }
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; }
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); }
int gcomm::PC::handle_down(Datagram& wb, const ProtoDownMeta& dm) { if (wb.len() == 0) { gu_throw_error(EMSGSIZE); } return send_down(wb, dm); }
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()); } }
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; }
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)); } }
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; }
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; }
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()); } }
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 }