lifomcom.cc

00001 /*
00002  *  Player - One Hell of a Robot Server
00003  *  Copyright (C) 2000  Brian Gerkey   &  Kasper Stoy
00004  *                      gerkey@usc.edu    kaspers@robotics.usc.edu
00005  *
00006  *  LifoMCom device by Matthew Brewer <mbrewer@andrew.cmu.edu> and 
00007  *  Reed Hedges <reed@zerohour.net> at the Laboratory for Perceptual 
00008  *  Robotics, Dept. of Computer Science, University of Massachusetts,
00009  *  Amherst.
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License
00022  *  along with this program; if not, write to the Free Software
00023  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  *
00025  */
00026 
00087 #include <string.h> 
00088 #include <sys/types.h>
00089 #include <netinet/in.h>
00090 
00091 #include "playercommon.h"
00092 
00093 #include "lifomcom.h"
00094 
00095 #ifdef MCOM_PLUGIN
00096 // todo dll stuff here
00097 #endif
00098 
00099 
00100 /*
00101 LifoMCom(int argc, char** argv):Driver(1,1,20,20),Data(){
00102 }
00103 */
00104 
00105 LifoMCom::LifoMCom( ConfigFile* cf, int section) 
00106   : Driver(cf, section, true, PLAYER_MSGQUEUE_DEFAULT_MAXLEN, PLAYER_MCOM_CODE, PLAYER_ALL_MODE)
00107 {
00108         printf("Constructing LifoMCom\n");
00109 }
00110 
00111 
00112 Driver* LifoMCom_Init( ConfigFile* cf, int section)
00113 {
00114   return((Driver*)(new LifoMCom( cf, section)));
00115 }
00116 
00117 
00118 void LifoMCom_Register(DriverTable* t) {
00119     t->AddDriver("lifomcom",  LifoMCom_Init);
00120 }
00121 
00123 // Process an incoming message
00124 int LifoMCom::ProcessMessage(ClientData * client, player_msghdr * hdr, uint8_t * data, uint8_t * resp_data, size_t * resp_len)
00125 {
00126   assert(hdr);
00127   assert(data);
00128   assert(resp_len);
00129   if (hdr->size < sizeof(player_mcom_config_t))
00130     return -1;
00131     
00132   player_mcom_config_t* cfg = reinterpret_cast<player_mcom_config_t*> (data);
00133   cfg->type = ntohs(cfg->type);
00134   
00135   if (MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_MCOM_REQ_PUSH, device_id))
00136   {
00137     Data.Push(cfg->data, cfg->type, cfg->channel);
00138         *resp_len = 0;
00139         return PLAYER_MSGTYPE_RESP_ACK;
00140   }
00141 
00142   if (MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_MCOM_REQ_POP, device_id))
00143   {
00144         assert(*resp_data >= sizeof(player_mcom_return_t));
00145         player_mcom_return_t & ret = *reinterpret_cast<player_mcom_return_t *> (resp_data);
00146     ret.data = Data.Pop(cfg->type, cfg->channel);
00147     if(ret.data.full) 
00148     {
00149       ret.type = htons(cfg->type);
00150       strcpy(ret.channel, cfg->channel);
00151       *resp_len = sizeof(player_mcom_return_t);
00152       return PLAYER_MSGTYPE_RESP_ACK;
00153     }
00154     else
00155     {
00156       *resp_len = 0;
00157       return PLAYER_MSGTYPE_RESP_NACK;
00158     }
00159   }
00160 
00161   if (MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_MCOM_REQ_READ, device_id))
00162   {
00163         assert(*resp_data >= sizeof(player_mcom_return_t));
00164         player_mcom_return_t & ret = *reinterpret_cast<player_mcom_return_t *> (resp_data);
00165 
00166     ret.data = Data.Read(cfg->type, cfg->channel);
00167     if(ret.data.full) 
00168     {
00169       ret.type = htons(cfg->type);
00170       strcpy(ret.channel, cfg->channel);
00171       Unlock();
00172       *resp_len = sizeof(player_mcom_return_t);
00173       return PLAYER_MSGTYPE_RESP_ACK;
00174     }
00175     else
00176     {
00177       *resp_len = 0;
00178       return PLAYER_MSGTYPE_RESP_NACK;
00179     }
00180   }      
00181       
00182   if (MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_MCOM_REQ_CLEAR, device_id))
00183   {
00184     Data.Clear(cfg->type, cfg->channel);
00185         *resp_len = 0;
00186         return PLAYER_MSGTYPE_RESP_ACK;
00187   }
00188 
00189   if (MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_MCOM_REQ_SET_CAPACITY, device_id))
00190   {
00191     Data.SetCapacity(cfg->type, cfg->channel, cfg->data.data[0]);
00192         *resp_len = 0;
00193         return PLAYER_MSGTYPE_RESP_ACK;
00194   }
00195 
00196   *resp_len = 0;
00197   return -1;
00198 }
00199 
00200 // called by player with config requests
00201 /*int 
00202 LifoMCom::PutConfig(player_device_id_t id, void *client, 
00203                     void* src, size_t len,
00204                     struct timeval* timestamp)
00205 {
00206     assert(len == sizeof(player_mcom_config_t));
00207     player_mcom_config_t* cfg = (player_mcom_config_t*)src;
00208     cfg->type = ntohs(cfg->type);
00209 
00210     // arguments to PutReply are: (void* client, ushort replytype, struct timeval* ts, void* data, size_t datalen)
00211     switch(cfg->command) {
00212         case PLAYER_MCOM_REQ_PUSH:
00213             Data.Push(cfg->data, cfg->type, cfg->channel);
00214             PutReply(client, PLAYER_MSGTYPE_RESP_ACK, NULL);
00215             return 0;
00216         case PLAYER_MCOM_REQ_POP:
00217             player_mcom_return_t ret;
00218             ret.data = Data.Pop(cfg->type, cfg->channel);
00219             if(ret.data.full) {
00220                 ret.type = htons(cfg->type);
00221                 strcpy(ret.channel, cfg->channel);
00222                 PutReply(client, PLAYER_MSGTYPE_RESP_ACK, &ret ,sizeof(ret), NULL);
00223                 return 0;
00224             } else {
00225                 PutReply(client, PLAYER_MSGTYPE_RESP_NACK, NULL);
00226                 return 0;
00227             }
00228             break;
00229         case PLAYER_MCOM_REQ_READ:
00230             ret.data = Data.Read(cfg->type, cfg->channel);
00231             if(ret.data.full) {
00232                 ret.type = htons(cfg->type);
00233                 strcpy(ret.channel, cfg->channel);
00234                 Unlock();
00235                 PutReply(client, PLAYER_MSGTYPE_RESP_ACK, &ret ,sizeof(ret),NULL);
00236                 return 0;
00237             } else {
00238                 Unlock();
00239                 PutReply(client, PLAYER_MSGTYPE_RESP_NACK, NULL);
00240                 return 0;
00241             }
00242             break;
00243          case PLAYER_MCOM_REQ_CLEAR:
00244             Data.Clear(cfg->type, cfg->channel);
00245             PutReply(client, PLAYER_MSGTYPE_RESP_ACK, NULL);
00246             return 0;
00247             
00248     case PLAYER_MCOM_REQ_SET_CAPACITY:
00249       
00250       Data.SetCapacity(cfg->type, cfg->channel, cfg->data.data[0]);
00251       PutReply(client, PLAYER_MSGTYPE_RESP_ACK, NULL);
00252       return 0;
00253 
00254         default:
00255             printf("Error: message %d to MCOM Device not recognized\n", cfg->command);
00256             PutReply(client, PLAYER_MSGTYPE_RESP_NACK, NULL);
00257             return 0;
00258     }
00259     return 0;
00260 }*/
00261 
00262 LifoMCom::Buffer::Buffer() {
00263     top = 0;
00264     capacity = MCOM_N_BUFS;
00265     for(int x = 0 ; x < MCOM_N_BUFS; x++) {
00266         dat[x].full=0;
00267         strcpy(dat[x].data,MCOM_EMPTY_STRING);
00268     }
00269 }
00270 
00271 LifoMCom::Buffer::~Buffer(){
00272 }
00273 
00274 void LifoMCom::Buffer::Push(player_mcom_data_t newdat) {
00275     top++;
00276     top %= capacity;
00277     //    if(top>=MCOM_N_BUFS)
00278     //        top-=MCOM_N_BUFS;
00279     
00280     dat[top]=newdat;
00281     dat[top].full=1;
00282 }
00283 
00284 player_mcom_data_t LifoMCom::Buffer::Pop(){
00285     player_mcom_data_t ret;
00286     ret=dat[top];
00287     dat[top].full=0;
00288     strcpy(dat[top].data, MCOM_EMPTY_STRING);
00289 
00290     if(--top < 0) {
00291       //        top+=MCOM_N_BUFS;
00292       top += capacity;
00293     }
00294     return ret;
00295 }
00296 
00297 player_mcom_data_t LifoMCom::Buffer::Read(){
00298     player_mcom_data_t ret;
00299     ret=dat[top];
00300     return ret;
00301 }
00302 
00303 void LifoMCom::Buffer::Clear(){
00304     int s;
00305     for(s=0;s<MCOM_N_BUFS;s++)
00306           dat[s].full=0;
00307 }
00308 
00309 void LifoMCom::Buffer::print(){
00310     int x;
00311     printf("mcom buffer dump of type %i channel %s buffer\n",type,channel);
00312     for(x=0;x<MCOM_N_BUFS;x++)
00313         printf("%s :: %i\n",dat[x].data,dat[x].full);
00314 }
00315 
00316 void
00317 LifoMCom::Buffer::SetCapacity(int cap) 
00318 {
00319   capacity = cap;
00320 }
00321 
00322 LifoMCom::LinkList::LinkList() : top(NULL) {
00323 }
00324 
00325 LifoMCom::LinkList::~LinkList(){
00326     Link *p=top;
00327     Link *next=p;
00328     while(p!=NULL){
00329         next=p->next;
00330         delete p;
00331         p=next;
00332     }
00333 }
00334 
00335 void LifoMCom::LinkList::Push(player_mcom_data_t d,int type, char channel[MCOM_CHANNEL_LEN]){
00336     Link * p=top;
00337     if(p==NULL){
00338         top=new Link;
00339         top->next=NULL;
00340         top->buf.type=type;
00341         strncpy(top->buf.channel, channel, MCOM_CHANNEL_LEN);
00342         p=top;
00343     } else {
00344         while(p->next!=NULL && (p->buf.type!=type || strcmp(p->buf.channel,channel))) {
00345             p=p->next;
00346         }
00347          
00348         if(p->buf.type!=type || strcmp(p->buf.channel,channel)){
00349             p->next = new Link;
00350             p=p->next;
00351             p->next=NULL;
00352             p->buf.type=type;
00353             strncpy(p->buf.channel, channel, MCOM_CHANNEL_LEN);
00354         }
00355     }
00356     p->buf.Push(d);
00357 }
00358 
00359 player_mcom_data_t LifoMCom::LinkList::Pop(int type, char channel[MCOM_CHANNEL_LEN]){
00360     Link *p=top;
00361     Link *last;
00362     player_mcom_data_t ret;
00363     strcpy(ret.data, MCOM_EMPTY_STRING);
00364     ret.full=0;
00365     if(p==NULL){
00366         return ret;
00367     }else{
00368         while(p->next!=NULL && (p->buf.type!=type || strcmp(p->buf.channel,channel))){
00369             last=p;
00370             p=p->next;
00371         }
00372         if(p->buf.type!=type || strcmp(p->buf.channel,channel)){
00373             return ret;
00374         }else{
00375             ret = p->buf.Pop();
00376 /*if(ret.full==0){
00377 printf("deleting buffer (it's empty)\n");
00378 if(p==top)
00379 delete top;
00380 else
00381 if(p==top->next){
00382 top->next=top->next->next;
00383 delete p;
00384 }else{
00385 last->next=p->next;
00386 delete p;
00387 }
00388 }*/
00389         }
00390     }
00391     return ret;
00392 }
00393 
00394 player_mcom_data_t LifoMCom::LinkList::Read(int type,char channel[MCOM_CHANNEL_LEN]){
00395     Link * p=top;
00396     player_mcom_data_t ret;
00397     ret.full=0;
00398     strcpy(ret.data, MCOM_EMPTY_STRING);
00399     if(p==NULL)
00400         return ret;
00401     else{
00402         while(p->next!=NULL && (p->buf.type!=type || strcmp(p->buf.channel,channel))){
00403             p=p->next;
00404         }
00405         if(p->buf.type!=type || strcmp(p->buf.channel,channel))
00406             return ret;
00407         else{
00408             return p->buf.Read();
00409         }
00410     }
00411 }
00412 
00413 void LifoMCom::LinkList::Clear(int type, char channel[MCOM_CHANNEL_LEN]) {
00414     Link *p = top;
00415     Link *last = NULL;
00416     if(p == NULL)
00417         return;
00418     else{
00419         while(p->next != NULL && (p->buf.type != type || strcmp(p->buf.channel, channel))){
00420             last = p;
00421             p = p->next;
00422         }
00423         if(p->buf.type != type || strcmp(p->buf.channel, channel))
00424             return;
00425         else{
00426             last->next=p->next->next;
00427             p->buf.Clear();
00428             delete p;
00429         }
00430     }
00431 }
00432 
00433 void
00434 LifoMCom::LinkList::SetCapacity(int type, char channel[MCOM_CHANNEL_LEN],
00435                                 unsigned char cap)
00436 {
00437   Link *link = FindLink(type, channel);
00438 
00439   if (link != NULL) {
00440     link->buf.SetCapacity((int)cap);
00441   }
00442 }
00443 
00444 LifoMCom::Link *
00445 LifoMCom::LinkList::FindLink(int type, char channel[MCOM_CHANNEL_LEN])
00446 {
00447   Link *p = top, *last = NULL;
00448   
00449   if (p == NULL) {
00450     return NULL;
00451   }
00452 
00453   while (p->next != NULL && (p->buf.type != type ||
00454                              strcmp(p->buf.channel, channel))) {
00455     last = p;
00456     p = p->next;
00457   }
00458 
00459   if (p->buf.type == type && !strcmp(p->buf.channel, channel)) {
00460     return p;
00461   }
00462 
00463   return NULL;
00464 }

Last updated 12 September 2005 21:38:45