00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <core/exceptions/system.h>
00025 #include <core/exceptions/software.h>
00026
00027 #include <netcomm/worldinfo/transceiver.h>
00028 #include <netcomm/worldinfo/messages.h>
00029 #include <netcomm/worldinfo/encrypt.h>
00030 #include <netcomm/worldinfo/decrypt.h>
00031
00032 #include <netcomm/socket/datagram_multicast.h>
00033 #include <netcomm/utils/resolver.h>
00034
00035 #include <utils/logging/liblogger.h>
00036
00037 #include <netinet/in.h>
00038 #include <cstdlib>
00039 #include <cstring>
00040
00041 namespace fawkes {
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 WorldInfoException::WorldInfoException(const char *msg)
00052 : Exception(msg)
00053 {
00054 }
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 WorldInfoTransceiver::WorldInfoTransceiver(const char *addr, unsigned short port,
00098 const char *key, const char *iv,
00099 NetworkNameResolver *resolver) :
00100 pose_changed( false ),
00101 vel_changed( false ),
00102 rel_ball_changed( false ),
00103 rel_ball_vel_changed( false ),
00104 glob_ball_changed( false ),
00105 glob_ball_vel_changed( false ),
00106 gamestate_changed( false )
00107 {
00108 try {
00109 s = new MulticastDatagramSocket(addr, port);
00110 s->bind();
00111 } catch (SocketException &e) {
00112 e.append("WorldInfoTransceiver cannot instantiate socket for %s:%u", addr, port);
00113 throw;
00114 }
00115
00116 in_buffer = malloc(WORLDINFO_MTU);
00117 out_buffer = malloc(WORLDINFO_MTU);
00118 if (! in_buffer || ! out_buffer) {
00119 throw OutOfMemoryException();
00120 }
00121
00122 fatmsg_enabled = false;
00123 fatmsg_bufsize = 0;
00124 fatmsg_buf = NULL;
00125 fatmsg_header = NULL;
00126 fatmsg_msgheader = NULL;
00127 fatmsg = NULL;
00128
00129 __key = strdup(key);
00130 __iv = strdup(iv);
00131
00132 encryptor = new WorldInfoMessageEncryptor((const unsigned char *)__key, (const unsigned char *)__iv);
00133 decryptor = new WorldInfoMessageDecryptor((const unsigned char *)__key, (const unsigned char *)__iv);
00134
00135
00136 encryptor->set_plain_buffer(out_buffer, WORLDINFO_MTU);
00137
00138 crypt_buffer_size = encryptor->recommended_crypt_buffer_size();
00139 crypted_out_buffer = malloc(crypt_buffer_size);
00140 crypted_in_buffer = malloc(crypt_buffer_size);
00141
00142 if (! crypted_in_buffer || ! crypted_out_buffer) {
00143 throw OutOfMemoryException();
00144 }
00145
00146 encryptor->set_crypt_buffer(crypted_out_buffer, crypt_buffer_size);
00147
00148 decryptor->set_plain_buffer(in_buffer, WORLDINFO_MTU);
00149
00150 if ( resolver == NULL ) {
00151 this->resolver = new NetworkNameResolver();
00152 resolver_delete = true;
00153 } else {
00154 this->resolver = resolver;
00155 resolver_delete = false;
00156 }
00157
00158 out_seq = 0;
00159 }
00160
00161
00162
00163 WorldInfoTransceiver::~WorldInfoTransceiver()
00164 {
00165 set_fatmsg_enabled(false);
00166 free(out_buffer);
00167 free(in_buffer);
00168 free(crypted_out_buffer);
00169 free(crypted_in_buffer);
00170 free(__key);
00171 free(__iv);
00172 delete s;
00173 delete encryptor;
00174 delete decryptor;
00175 if ( resolver_delete ) {
00176 delete resolver;
00177 }
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187 void
00188 WorldInfoTransceiver::set_loop(bool loop)
00189 {
00190 s->set_loop( loop );
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200 void
00201 WorldInfoTransceiver::set_fatmsg_enabled(bool fatmsg_enabled)
00202 {
00203 if ( this->fatmsg_enabled && ! fatmsg_enabled ) {
00204
00205 free(fatmsg_buf);
00206 fatmsg_buf = NULL;
00207 fatmsg_msgheader = NULL;
00208 fatmsg_header = NULL;
00209 fatmsg = NULL;
00210 fatmsg_bufsize = 0;
00211 } else if (! this->fatmsg_enabled && fatmsg_enabled ) {
00212
00213 fatmsg_bufsize = sizeof(worldinfo_header_t) + sizeof(worldinfo_message_header_t)
00214 + sizeof(worldinfo_fat_message_t);
00215 fatmsg_buf = calloc(1, fatmsg_bufsize);
00216 fatmsg_header = (worldinfo_header_t *)fatmsg_buf;
00217 fatmsg_msgheader = (worldinfo_message_header_t *)((char *)fatmsg_buf + sizeof(worldinfo_header_t));
00218 fatmsg = (worldinfo_fat_message_t *)((char *)fatmsg_buf + sizeof(worldinfo_header_t)
00219 + sizeof(worldinfo_message_header_t));
00220 }
00221
00222 this->fatmsg_enabled = fatmsg_enabled;
00223 }
00224
00225
00226
00227
00228
00229
00230
00231 void
00232 WorldInfoTransceiver::add_handler(WorldInfoHandler *h)
00233 {
00234 handlers.lock();
00235 handlers.push_back(h);
00236 handlers.sort();
00237 handlers.unique();
00238 handlers.unlock();
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248 void
00249 WorldInfoTransceiver::rem_handler(WorldInfoHandler *h)
00250 {
00251 handlers.remove_locked(h);
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 void
00264 WorldInfoTransceiver::flush_sequence_numbers(unsigned int sec)
00265 {
00266 time_t limit = time(NULL) - sec;
00267
00268 std::map<uint32_t, time_t>::iterator lrtit2;
00269 lrtit = last_received_time.begin();
00270 while (lrtit != last_received_time.end()) {
00271 if ( (*lrtit).second < limit ) {
00272 sequence_numbers.erase((*lrtit).first);
00273 lrtit2 = lrtit;
00274 ++lrtit;
00275 last_received_time.erase(lrtit2);
00276 } else {
00277 ++lrtit;
00278 }
00279 }
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 void
00301 WorldInfoTransceiver::set_pose(float x, float y, float theta, float *covariance)
00302 {
00303 pose_x = x;
00304 pose_y = y;
00305 pose_theta = theta;
00306 pose_covariance = covariance;
00307 pose_changed = true;
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 void
00324 WorldInfoTransceiver::set_velocity(float vel_x, float vel_y, float vel_theta, float *covariance)
00325 {
00326 this->vel_x = vel_x;
00327 this->vel_y = vel_y;
00328 this->vel_theta = vel_theta;
00329 this->vel_covariance = covariance;
00330 this->vel_changed = true;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 void
00350 WorldInfoTransceiver::set_rel_ball_pos(float dist, float bearing, float slope, float *covariance)
00351 {
00352 rel_ball_dist = dist;
00353 rel_ball_bearing = bearing;
00354 rel_ball_slope = slope;
00355 rel_ball_covariance = covariance;
00356 rel_ball_changed = true;
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 void
00375 WorldInfoTransceiver::set_glob_ball_pos(float x, float y, float z, float *covariance)
00376 {
00377 glob_ball_x = x;
00378 glob_ball_y = y;
00379 glob_ball_z = z;
00380 glob_ball_covariance = covariance;
00381 glob_ball_changed = true;
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 void
00398 WorldInfoTransceiver::set_rel_ball_visible(bool visible, int visibility_history)
00399 {
00400 rel_ball_visible = visible;
00401 rel_ball_visibility_history = visibility_history;
00402 rel_ball_changed = true;
00403 }
00404
00405
00406
00407
00408
00409
00410
00411 void
00412 WorldInfoTransceiver::set_glob_ball_visible(bool visible, int visibility_history)
00413 {
00414 glob_ball_visible = visible;
00415 glob_ball_visibility_history = visibility_history;
00416 glob_ball_changed = true;
00417 }
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 void
00432 WorldInfoTransceiver::set_rel_ball_velocity(float vel_x, float vel_y, float vel_z,
00433 float *covariance)
00434 {
00435 rel_ball_vel_x = vel_x;
00436 rel_ball_vel_y = vel_y;
00437 rel_ball_vel_z = vel_z;
00438 rel_ball_vel_covariance = covariance;
00439 rel_ball_vel_changed = true;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 void
00455 WorldInfoTransceiver::set_glob_ball_velocity(float vel_x, float vel_y, float vel_z,
00456 float *covariance)
00457 {
00458 glob_ball_vel_x = vel_x;
00459 glob_ball_vel_y = vel_y;
00460 glob_ball_vel_z = vel_z;
00461 glob_ball_vel_covariance = covariance;
00462 glob_ball_vel_changed = true;
00463 }
00464
00465
00466
00467
00468
00469
00470 void
00471 WorldInfoTransceiver::set_gamestate(int gamestate,
00472 worldinfo_gamestate_team_t state_team)
00473 {
00474 if ((gamestate < 0) || (gamestate >= 16)) {
00475 throw OutOfBoundsException("Illegal gamestate", gamestate, 0, 15);
00476 }
00477 gamestate_msg.game_state = gamestate;
00478 gamestate_msg.state_team = state_team;
00479 gamestate_changed = true;
00480 }
00481
00482
00483
00484
00485
00486
00487 void
00488 WorldInfoTransceiver::set_score(unsigned int score_cyan, unsigned int score_magenta)
00489 {
00490 gamestate_msg.score_cyan = score_cyan;
00491 gamestate_msg.score_magenta = score_magenta;
00492 gamestate_changed = true;
00493 }
00494
00495
00496
00497
00498
00499
00500
00501 void
00502 WorldInfoTransceiver::add_penalty(unsigned int player, unsigned int penalty,
00503 unsigned int seconds_remaining)
00504 {
00505 worldinfo_penalty_message_t pm;
00506 pm.reserved = 0;
00507 pm.player = player;
00508 pm.penalty = penalty;
00509 pm.seconds_remaining = seconds_remaining;
00510 penalties[player] = pm;
00511 }
00512
00513
00514
00515
00516
00517 void
00518 WorldInfoTransceiver::set_team_goal(worldinfo_gamestate_team_t our_team,
00519 worldinfo_gamestate_goalcolor_t goal_color)
00520 {
00521 gamestate_msg.our_team = our_team;
00522 gamestate_msg.our_goal_color = goal_color;
00523 gamestate_changed = true;
00524 }
00525
00526
00527
00528
00529
00530 void
00531 WorldInfoTransceiver::set_half(worldinfo_gamestate_half_t half)
00532 {
00533 gamestate_msg.half = half;
00534 gamestate_changed = true;
00535 }
00536
00537
00538
00539
00540
00541
00542 void
00543 WorldInfoTransceiver::clear_opponents()
00544 {
00545 opponents.clear();
00546 }
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 void
00566 WorldInfoTransceiver::add_opponent(unsigned int uid,
00567 float distance, float bearing, float *covariance)
00568 {
00569 opponent_t o = { uid, distance, bearing, covariance };
00570 opponents.push_back(o);
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580 void
00581 WorldInfoTransceiver::add_disappeared_opponent(unsigned int uid)
00582 {
00583 disappeared_opponents.push_back(uid);
00584 }
00585
00586
00587
00588
00589
00590
00591
00592
00593 void
00594 WorldInfoTransceiver::append_outbound(uint16_t msg_type,
00595 void *msg, uint16_t msg_size)
00596 {
00597 worldinfo_message_header_t mh;
00598
00599 if ( (outbound_bytes + sizeof(mh) + msg_size ) > WORLDINFO_MTU ) {
00600 throw OutOfMemoryException();
00601 }
00602
00603
00604 mh.type = htons(msg_type);
00605 mh.size = htons(msg_size);
00606 memcpy(outbound_buffer, &mh, sizeof(mh));
00607
00608 outbound_bytes += sizeof(mh);
00609 outbound_buffer += sizeof(mh);
00610
00611
00612 memcpy(outbound_buffer, msg, msg_size);
00613 outbound_bytes += msg_size;
00614 outbound_buffer += msg_size;
00615 ++outbound_num_msgs;
00616 }
00617
00618
00619
00620
00621 void
00622 WorldInfoTransceiver::reset_outbound()
00623 {
00624 worldinfo_header_t *header = (worldinfo_header_t *)out_buffer;
00625 header->beef = htons(0xBEEF);
00626 header->version = WORLDINFO_VERSION;
00627
00628 if ( fatmsg_enabled ) {
00629 memset(fatmsg_buf, 0, fatmsg_bufsize);
00630 fatmsg_header->beef = htons(0xBEEF);
00631 fatmsg_header->version = WORLDINFO_VERSION;
00632 fatmsg_msgheader->type = htons(WORLDINFO_MSGTYPE_FAT_WORLDINFO);
00633 fatmsg_msgheader->size = htons(sizeof(worldinfo_fat_message_t));
00634 }
00635
00636 outbound_buffer = (unsigned char *)out_buffer + sizeof(worldinfo_header_t);
00637 outbound_bytes = sizeof(worldinfo_header_t);
00638 outbound_num_msgs = 0;
00639 }
00640
00641
00642
00643
00644
00645
00646 void
00647 WorldInfoTransceiver::send()
00648 {
00649 worldinfo_header_t *header = (worldinfo_header_t *)out_buffer;
00650
00651 reset_outbound();
00652
00653 if ( pose_changed ) {
00654 worldinfo_pose_message_t pm;
00655 pm.x = pose_x;
00656 pm.y = pose_y;
00657 pm.theta = pose_theta;
00658 memcpy(&(pm.covariance), pose_covariance, sizeof(pm.covariance));
00659 pose_changed = false;
00660
00661 append_outbound(WORLDINFO_MSGTYPE_POSE, &pm, sizeof(pm));
00662
00663 if ( fatmsg_enabled ) {
00664
00665 memcpy(&(fatmsg->pose), &pm, sizeof(pm));
00666 fatmsg->valid_pose = 1;
00667 }
00668 } else {
00669 if ( fatmsg_enabled ) {
00670 fatmsg->valid_pose = 0;
00671 }
00672 }
00673
00674 if ( vel_changed ) {
00675 worldinfo_velocity_message_t vm;
00676 vm.vel_x = vel_x;
00677 vm.vel_y = vel_y;
00678 vm.vel_theta = vel_theta;
00679 memcpy(&(vm.covariance), vel_covariance, sizeof(vm.covariance));
00680 vel_changed = false;
00681
00682 append_outbound(WORLDINFO_MSGTYPE_VELO, &vm, sizeof(vm));
00683
00684 if ( fatmsg_enabled ) {
00685
00686 memcpy(&(fatmsg->velo), &vm, sizeof(vm));
00687 fatmsg->valid_velo = 1;
00688 }
00689 } else {
00690 if ( fatmsg_enabled ) {
00691 fatmsg->valid_velo = 0;
00692 }
00693 }
00694
00695 if ( rel_ball_changed ) {
00696 worldinfo_relballpos_message_t bm;
00697 bm.dist = rel_ball_dist;
00698 bm.bearing = rel_ball_bearing;
00699 bm.slope = rel_ball_slope;
00700 bm.history = rel_ball_visibility_history;
00701 bm.visible = rel_ball_visible ? -1 : 0;
00702 memcpy(&(bm.covariance), rel_ball_covariance, sizeof(bm.covariance));
00703
00704 rel_ball_changed = false;
00705
00706 append_outbound(WORLDINFO_MSGTYPE_GLOBBALL, &bm, sizeof(bm));
00707
00708 if ( fatmsg_enabled ) {
00709
00710 memcpy(&(fatmsg->relball_pos), &bm, sizeof(bm));
00711 fatmsg->valid_relball_pos = 1;
00712 }
00713 } else {
00714 if ( fatmsg_enabled ) {
00715 fatmsg->valid_relball_pos = 0;
00716 }
00717 }
00718
00719 if ( glob_ball_changed ) {
00720 worldinfo_globballpos_message_t bm;
00721 bm.x = glob_ball_x;
00722 bm.y = glob_ball_y;
00723 bm.z = glob_ball_z;
00724 bm.history = glob_ball_visibility_history;
00725 bm.visible = glob_ball_visible ? -1 : 0;
00726 memcpy(&(bm.covariance), glob_ball_covariance, sizeof(bm.covariance));
00727
00728 glob_ball_changed = false;
00729
00730 append_outbound(WORLDINFO_MSGTYPE_GLOBBALL, &bm, sizeof(bm));
00731 }
00732
00733 if ( gamestate_changed ) {
00734 append_outbound(WORLDINFO_MSGTYPE_GAMESTATE,
00735 &gamestate_msg, sizeof(worldinfo_gamestate_message_t));
00736 gamestate_changed = false;
00737 }
00738
00739 if ( rel_ball_vel_changed ) {
00740 worldinfo_relballvelo_message_t rbvm;
00741 rbvm.vel_x = rel_ball_vel_x;
00742 rbvm.vel_y = rel_ball_vel_y;
00743 rbvm.vel_z = rel_ball_vel_z;
00744 memcpy(&(rbvm.covariance), rel_ball_vel_covariance, sizeof(rbvm.covariance));
00745 rel_ball_vel_changed = false;
00746
00747 append_outbound(WORLDINFO_MSGTYPE_RELBALLVELO, &rbvm, sizeof(rbvm));
00748
00749 if ( fatmsg_enabled ) {
00750
00751 memcpy(&(fatmsg->relball_velo), &rbvm, sizeof(rbvm));
00752 fatmsg->valid_relball_velo = 1;
00753 }
00754 } else {
00755 if ( fatmsg_enabled ) {
00756 fatmsg->valid_relball_velo = 0;
00757 }
00758 }
00759
00760 if ( glob_ball_vel_changed ) {
00761 worldinfo_globballvelo_message_t rbvm;
00762 rbvm.vel_x = glob_ball_vel_x;
00763 rbvm.vel_y = glob_ball_vel_y;
00764 rbvm.vel_z = glob_ball_vel_z;
00765 memcpy(&(rbvm.covariance), glob_ball_vel_covariance, sizeof(rbvm.covariance));
00766 glob_ball_vel_changed = false;
00767
00768 append_outbound(WORLDINFO_MSGTYPE_GLOBBALLVELO, &rbvm, sizeof(rbvm));
00769 }
00770
00771
00772 for (penit = penalties.begin(); penit != penalties.end(); ++penit) {
00773 append_outbound(WORLDINFO_MSGTYPE_PENALTY,
00774 &(penit->second), sizeof(worldinfo_penalty_message_t));
00775 }
00776 penalties.clear();
00777
00778
00779 unsigned int num_opponents = 0;
00780 for ( oppit = opponents.begin(); oppit != opponents.end(); ++oppit) {
00781 worldinfo_opppose_message_t opm;
00782 opm.uid = (*oppit).uid;
00783 opm.dist = (*oppit).distance;
00784 opm.bearing = (*oppit).bearing;
00785 memcpy(&(opm.covariance), (*oppit).covariance, sizeof(opm.covariance));
00786
00787 append_outbound(WORLDINFO_MSGTYPE_OPP_POSE, &opm, sizeof(opm));
00788
00789 if ( fatmsg_enabled ) {
00790 if ( num_opponents < WORLDINFO_FATMSG_NUMOPPS ) {
00791
00792 memcpy(&(fatmsg->opponents[num_opponents]), &opm, sizeof(opm));
00793 ++num_opponents;
00794 fatmsg->num_opponents = num_opponents;
00795 }
00796 }
00797 }
00798 opponents.clear();
00799
00800 for ( doppit = disappeared_opponents.begin(); doppit != disappeared_opponents.end(); ++doppit) {
00801 worldinfo_oppdisappeared_message_t opdm;
00802 opdm.uid = *doppit;
00803
00804 append_outbound(WORLDINFO_MSGTYPE_OPP_DISAPP, &opdm, sizeof(opdm));
00805 }
00806 disappeared_opponents.clear();
00807
00808 if ( outbound_num_msgs > 0 ) {
00809
00810 header->seq = htonl(out_seq++);
00811
00812 encryptor->set_plain_buffer(out_buffer, outbound_bytes);
00813 crypted_out_bytes = encryptor->encrypt();
00814
00815 s->send(crypted_out_buffer, crypted_out_bytes);
00816
00817 if ( fatmsg_enabled ) {
00818
00819 fatmsg_header->seq = htonl(out_seq++);
00820
00821 encryptor->set_plain_buffer(fatmsg_buf, fatmsg_bufsize);
00822 crypted_out_bytes = encryptor->encrypt();
00823
00824 s->send(crypted_out_buffer, crypted_out_bytes);
00825 }
00826 }
00827
00828 }
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854 void
00855 WorldInfoTransceiver::recv(bool block, unsigned int max_num_msgs)
00856 {
00857 if ( ! block ) {
00858 if ( ! s->available() ) {
00859 return;
00860 }
00861 }
00862
00863 handlers.lock();
00864
00865 unsigned int num_msgs = (max_num_msgs == 0 ? 0 : 1);
00866 do {
00867 struct sockaddr_in from;
00868 socklen_t addr_len = sizeof(from);
00869 size_t bytes = crypt_buffer_size;
00870
00871 if ( max_num_msgs != 0 ) ++num_msgs;
00872
00873 bytes = s->recv(crypted_in_buffer, bytes, (struct sockaddr *)&from, &addr_len);
00874
00875
00876 decryptor->set_crypt_buffer(crypted_in_buffer, bytes);
00877 try {
00878 inbound_bytes = decryptor->decrypt();
00879 } catch (MessageDecryptionException &e) {
00880 LibLogger::log_warn("WorldInfoTransceiver", "Message decryption failed, ignoring");
00881 LibLogger::log_warn("WorldInfoTransceiver", e);
00882 continue;
00883 }
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 worldinfo_header_t *header = (worldinfo_header_t *)in_buffer;
00896 if ( ntohs(header->beef) != 0xBEEF ) {
00897
00898 LibLogger::log_warn("WorldInfoTransceiver", "Invalid message received (no 0xBEEF), ignoring");
00899 continue;
00900 }
00901
00902 if ( header->version != WORLDINFO_VERSION ) {
00903 LibLogger::log_warn("WorldInfoTransceiver", "Unsupported version of world info data received, ignoring");
00904 continue;
00905 }
00906
00907
00908
00909 unsigned int cseq = ntohl(header->seq);
00910 if ( sequence_numbers.find(from.sin_addr.s_addr) != sequence_numbers.end() ) {
00911 if ( cseq <= sequence_numbers[from.sin_addr.s_addr] ) {
00912
00913 LibLogger::log_warn("WorldInfoTransceiver", "Received packet twice, ignoring");
00914 continue;
00915 }
00916 }
00917 sequence_numbers[from.sin_addr.s_addr] = cseq;
00918 last_received_time[from.sin_addr.s_addr] = time(NULL);
00919
00920 inbound_bytes -= sizeof(worldinfo_header_t);
00921 inbound_buffer = (unsigned char *)in_buffer + sizeof(worldinfo_header_t);
00922
00923 std::string hostname_s;
00924 if ( ! resolver->resolve_address((struct sockaddr *)&from, sizeof(from), hostname_s) ) {
00925 hostname_s = "unknown";
00926 }
00927 const char *hostname = hostname_s.c_str();
00928
00929
00930 while ( inbound_bytes > 0 ) {
00931 worldinfo_message_header_t *msgh = (worldinfo_message_header_t *)inbound_buffer;
00932 inbound_bytes -= sizeof(worldinfo_message_header_t);
00933 inbound_buffer += sizeof(worldinfo_message_header_t);
00934 uint16_t msg_type = ntohs(msgh->type);
00935 uint16_t msg_size = ntohs(msgh->size);
00936
00937
00938 if ( inbound_bytes < msg_size ) {
00939 LibLogger::log_warn("WorldInfoTransceiver", "Truncated packet received or protocol "
00940 "error, ignoring rest of packet (got %zu bytes, but expected "
00941 "%zu bytes)", inbound_bytes, msg_size);
00942 break;
00943 }
00944 switch ( msg_type ) {
00945 case WORLDINFO_MSGTYPE_POSE:
00946 if ( msg_size == sizeof(worldinfo_pose_message_t) ) {
00947 worldinfo_pose_message_t *pose_msg = (worldinfo_pose_message_t *)inbound_buffer;
00948 for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
00949 (*hit)->pose_rcvd(hostname,
00950 pose_msg->x, pose_msg->y, pose_msg->theta,
00951 pose_msg->covariance);
00952 }
00953 } else {
00954 LibLogger::log_warn("WorldInfoTransceiver", "Invalid pose message received "
00955 "(got %zu bytes but expected %zu bytes), ignoring",
00956 msg_size, sizeof(worldinfo_pose_message_t));
00957 }
00958 break;
00959
00960 case WORLDINFO_MSGTYPE_VELO:
00961 if ( msg_size == sizeof(worldinfo_velocity_message_t) ) {
00962 worldinfo_velocity_message_t *velo_msg = (worldinfo_velocity_message_t *)inbound_buffer;
00963 for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
00964 (*hit)->velocity_rcvd(hostname,
00965 velo_msg->vel_x, velo_msg->vel_y, velo_msg->vel_theta,
00966 velo_msg->covariance);
00967 }
00968 } else {
00969 LibLogger::log_warn("WorldInfoTransceiver", "Invalid velocity message received "
00970 "(got %zu bytes but expected %zu bytes), ignoring",
00971 msg_size, sizeof(worldinfo_velocity_message_t));
00972 }
00973 break;
00974
00975 case WORLDINFO_MSGTYPE_RELBALL:
00976 if ( msg_size == sizeof(worldinfo_relballpos_message_t) ) {
00977 worldinfo_relballpos_message_t *ball_msg = (worldinfo_relballpos_message_t *)inbound_buffer;
00978 for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
00979 (*hit)->ball_pos_rcvd(hostname,
00980 (ball_msg->visible == -1), ball_msg->history,
00981 ball_msg->dist, ball_msg->bearing, ball_msg->slope,
00982 ball_msg->covariance);
00983 }
00984 } else {
00985 LibLogger::log_warn("WorldInfoTransceiver", "Invalid relative ball pos message received "
00986 "(got %zu bytes but expected %zu bytes), ignoring",
00987 msg_size, sizeof(worldinfo_relballpos_message_t));
00988 }
00989 break;
00990
00991 case WORLDINFO_MSGTYPE_GLOBBALL:
00992 if ( msg_size == sizeof(worldinfo_globballpos_message_t) ) {
00993 worldinfo_globballpos_message_t *ball_msg = (worldinfo_globballpos_message_t *)inbound_buffer;
00994 for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
00995 (*hit)->global_ball_pos_rcvd(hostname,
00996 (ball_msg->visible == -1), ball_msg->history,
00997 ball_msg->x, ball_msg->y, ball_msg->z,
00998 ball_msg->covariance);
00999 }
01000 } else {
01001 LibLogger::log_warn("WorldInfoTransceiver", "Invalid global ball pos message received "
01002 "(got %zu bytes but expected %zu bytes), ignoring",
01003 msg_size, sizeof(worldinfo_globballpos_message_t));
01004 }
01005 break;
01006
01007 case WORLDINFO_MSGTYPE_RELBALLVELO:
01008 if ( msg_size == sizeof(worldinfo_relballvelo_message_t) ) {
01009 worldinfo_relballvelo_message_t *bvel_msg = (worldinfo_relballvelo_message_t *)inbound_buffer;
01010 for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
01011 (*hit)->ball_velocity_rcvd(hostname,
01012 bvel_msg->vel_x, bvel_msg->vel_y, bvel_msg->vel_z,
01013 bvel_msg->covariance);
01014 }
01015 } else {
01016 LibLogger::log_warn("WorldInfoTransceiver", "Invalid relative ball velocity message received "
01017 "(got %zu bytes but expected %zu bytes), ignoring",
01018 msg_size, sizeof(worldinfo_relballvelo_message_t));
01019 }
01020 break;
01021
01022 case WORLDINFO_MSGTYPE_GLOBBALLVELO:
01023 if ( msg_size == sizeof(worldinfo_globballvelo_message_t) ) {
01024 worldinfo_globballvelo_message_t *bvel_msg = (worldinfo_globballvelo_message_t *)inbound_buffer;
01025 for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
01026 (*hit)->global_ball_velocity_rcvd(hostname,
01027 bvel_msg->vel_x, bvel_msg->vel_y, bvel_msg->vel_z,
01028 bvel_msg->covariance);
01029 }
01030 } else {
01031 LibLogger::log_warn("WorldInfoTransceiver", "Invalid global ball velocity message received "
01032 "(got %zu bytes but expected %zu bytes), ignoring",
01033 msg_size, sizeof(worldinfo_globballvelo_message_t));
01034 }
01035 break;
01036
01037 case WORLDINFO_MSGTYPE_OPP_POSE:
01038 if ( msg_size == sizeof(worldinfo_opppose_message_t) ) {
01039 worldinfo_opppose_message_t *oppp_msg = (worldinfo_opppose_message_t *)inbound_buffer;
01040 for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
01041 (*hit)->opponent_pose_rcvd(hostname,
01042 oppp_msg->uid, oppp_msg->dist, oppp_msg->bearing,
01043 oppp_msg->covariance);
01044 }
01045 } else {
01046 LibLogger::log_warn("WorldInfoTransceiver", "Invalid opponent pose message received "
01047 "(got %zu bytes but expected %zu bytes), ignoring",
01048 msg_size, sizeof(worldinfo_opppose_message_t));
01049 }
01050 break;
01051
01052 case WORLDINFO_MSGTYPE_OPP_DISAPP:
01053 if ( msg_size == sizeof(worldinfo_oppdisappeared_message_t) ) {
01054 worldinfo_oppdisappeared_message_t *oppd_msg = (worldinfo_oppdisappeared_message_t *)inbound_buffer;
01055 for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
01056 (*hit)->opponent_disapp_rcvd(hostname, oppd_msg->uid);
01057 }
01058 } else {
01059 LibLogger::log_warn("WorldInfoTransceiver", "Invalid opponent disappeared message received "
01060 "(got %zu bytes but expected %zu bytes), ignoring",
01061 msg_size, sizeof(worldinfo_oppdisappeared_message_t));
01062 }
01063 break;
01064
01065 case WORLDINFO_MSGTYPE_GAMESTATE:
01066 if ( msg_size == sizeof(worldinfo_gamestate_message_t) ) {
01067 worldinfo_gamestate_message_t *gs_msg = (worldinfo_gamestate_message_t *)inbound_buffer;
01068 for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
01069 (*hit)->gamestate_rcvd(hostname,
01070 gs_msg->game_state,
01071 (worldinfo_gamestate_team_t)gs_msg->state_team,
01072 gs_msg->score_cyan, gs_msg->score_magenta,
01073 (worldinfo_gamestate_team_t)gs_msg->our_team,
01074 (worldinfo_gamestate_goalcolor_t)gs_msg->our_goal_color,
01075 (worldinfo_gamestate_half_t)gs_msg->half);
01076 }
01077 } else {
01078 LibLogger::log_warn("WorldInfoTransceiver", "Invalid gamestate message received "
01079 "(got %zu bytes but expected %zu bytes), ignoring",
01080 msg_size, sizeof(worldinfo_gamestate_message_t));
01081 }
01082 break;
01083
01084 case WORLDINFO_MSGTYPE_PENALTY:
01085 if ( msg_size == sizeof(worldinfo_penalty_message_t) ) {
01086 worldinfo_penalty_message_t *p_msg = (worldinfo_penalty_message_t *)inbound_buffer;
01087 for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
01088 (*hit)->penalty_rcvd(hostname,
01089 p_msg->player, p_msg->penalty, p_msg->seconds_remaining);
01090 }
01091
01092 } else {
01093 LibLogger::log_warn("WorldInfoTransceiver", "Invalid penalty message received "
01094 "(got %zu bytes but expected %zu bytes), ignoring",
01095 msg_size, sizeof(worldinfo_penalty_message_t));
01096 }
01097 break;
01098
01099 case WORLDINFO_MSGTYPE_FAT_WORLDINFO:
01100 if ( msg_size == sizeof(worldinfo_fat_message_t) ) {
01101 worldinfo_fat_message_t *fat_msg = (worldinfo_fat_message_t *)inbound_buffer;
01102 for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
01103 if ( fat_msg->valid_pose ) {
01104 (*hit)->pose_rcvd(hostname,
01105 fat_msg->pose.x, fat_msg->pose.y, fat_msg->pose.theta,
01106 fat_msg->pose.covariance);
01107 }
01108
01109 if ( fat_msg->valid_velo ) {
01110 (*hit)->velocity_rcvd(hostname,
01111 fat_msg->velo.vel_x, fat_msg->velo.vel_y,
01112 fat_msg->velo.vel_theta, fat_msg->velo.covariance);
01113 }
01114 if ( fat_msg->valid_relball_pos ) {
01115 (*hit)->ball_pos_rcvd(hostname,
01116 (fat_msg->relball_pos.visible == -1),
01117 fat_msg->relball_pos.history,
01118 fat_msg->relball_pos.dist, fat_msg->relball_pos.bearing,
01119 fat_msg->relball_pos.slope, fat_msg->relball_pos.covariance);
01120 }
01121 if ( fat_msg->valid_relball_velo ) {
01122 (*hit)->ball_velocity_rcvd(hostname,
01123 fat_msg->relball_velo.vel_x,
01124 fat_msg->relball_velo.vel_y,
01125 fat_msg->relball_velo.vel_z,
01126 fat_msg->relball_velo.covariance);
01127 }
01128
01129 if ( fat_msg->num_opponents > WORLDINFO_FATMSG_NUMOPPS ) {
01130
01131 LibLogger::log_warn("WorldInfoTransceiver", "Too many opponents marked valid in message "
01132 "(got %zu but expected a maximum of %zu), ignoring",
01133 fat_msg->num_opponents, WORLDINFO_FATMSG_NUMOPPS);
01134 } else {
01135 for ( unsigned int i = 0; i < fat_msg->num_opponents; ++i ) {
01136 (*hit)->opponent_pose_rcvd(hostname,
01137 fat_msg->opponents[i].uid,
01138 fat_msg->opponents[i].dist,
01139 fat_msg->opponents[i].bearing,
01140 fat_msg->opponents[i].covariance);
01141 }
01142 }
01143 }
01144 } else {
01145 LibLogger::log_warn("WorldInfoTransceiver", "Invalid fat message received "
01146 "(got %zu bytes but expected %zu bytes), ignoring",
01147 msg_size, sizeof(worldinfo_fat_message_t));
01148 }
01149 break;
01150
01151
01152 default:
01153 LibLogger::log_warn("WorldInfoTransceiver", "Unknown message type %u received "
01154 ", ignoring", msg_type);
01155 }
01156
01157 inbound_bytes -= msg_size;
01158 inbound_buffer += msg_size;
01159 }
01160
01161 } while ( s->available() && (num_msgs <= max_num_msgs) );
01162
01163 handlers.unlock();
01164 }
01165
01166
01167
01168
01169
01170
01171 void *
01172 WorldInfoTransceiver::last_sent_plain_buffer()
01173 {
01174 return out_buffer;
01175 }
01176
01177
01178
01179
01180
01181
01182 size_t
01183 WorldInfoTransceiver::last_sent_plain_buffer_size()
01184 {
01185 return outbound_bytes;
01186 }
01187
01188
01189
01190
01191
01192
01193 void *
01194 WorldInfoTransceiver::last_sent_crypted_buffer()
01195 {
01196 return crypted_out_buffer;
01197 }
01198
01199
01200
01201
01202
01203
01204 size_t
01205 WorldInfoTransceiver::last_sent_crypted_buffer_size()
01206 {
01207 return crypted_out_bytes;
01208 }
01209
01210 }