Go to the documentation of this file.00001 #include <assert.h>
00002 #include <string.h>
00003 #include <errno.h>
00004
00005 #include "canon_vbc50i/libCanon/XString.h"
00006 #include "canon_vbc50i/libCanon/CommManager.h"
00007 #include "canon_vbc50i/libCanon/login.h"
00008
00009
00010 CommManager::CommManager(const char * initseq_filename)
00011 {
00012 sock = NULL;
00013 verbose = 1;
00014 in_thread = 0;
00015 terminate = false;
00016 pthread_mutex_init(&sockmtx,NULL);
00017 Q.setVerboseLevel(1);
00018
00019 Datagram dgm;
00020 bool loginFromFile = false;
00021 FILE * fp = NULL;
00022 if (initseq_filename) {
00023 fp = fopen(initseq_filename,"r");
00024 if (fp == NULL) {
00025 fprintf(stderr,"CommManager: Could not open '%s'\n",initseq_filename);
00026 } else {
00027 loginFromFile = true;
00028 }
00029 }
00030 if (loginFromFile) {
00031 while (1) {
00032 if (!dgm.read(fp)) break;
00033
00034 init_seq.push_back(dgm);
00035 }
00036 fclose(fp);
00037 } else {
00038 printf("Using builtin login sequence\n");
00039 RawBinDatagram * bdgm = raw_bin_login;
00040 while (bdgm->len != 0) {
00041 if (!dgm.read(bdgm->data,bdgm->len)) break;
00042
00043 init_seq.push_back(dgm);
00044 bdgm ++;
00045 }
00046 }
00047 #ifdef CM_CARE_FOR_REPLY
00048 init_reply.resize(init_seq.size());
00049 #endif
00050 }
00051
00052 CommManager::~CommManager()
00053 {
00054 close();
00055 }
00056
00057 void * commmanager_inthread(void * arg)
00058 {
00059 CommManager * cm = (CommManager*)arg;
00060 cm->run();
00061 return NULL;
00062 }
00063
00064 bool CommManager::sendInitSeq()
00065 {
00066 unsigned int i;
00067 Datagram dgm;
00068 for (i=0;i<init_seq.size();i++) {
00069 if (!send(init_seq[i])) {
00070 printf("%s: Can't send datagram %d:",__FUNCTION__,i);
00071 init_seq[i].write(stdout);
00072 printf("\n");
00073 goto cleanup;
00074 }
00075 if (!sock->WaitData((i==0)?1000:100)) {
00076 printf("No answer for datagram %d\n",i);
00077 goto cleanup;
00078 }
00079 if (!dgm.receive(sock)) {
00080 printf("Error receiving answer for datagram %d\n",i);
00081 goto cleanup;
00082 }
00083 if (verbose > 1) {
00084 printf("Received: ");dgm.print(stdout);
00085 }
00086 #ifdef CM_CARE_FOR_REPLY
00087 init_reply[i] = dgm;
00088 #endif
00089 }
00090
00091 printf("CM: Initialization completed\n");
00092 return true;
00093 cleanup:
00094 printf("CM: Initialization failed\n");
00095 return false;
00096 }
00097
00098
00099 bool CommManager::open(const char * hostname, unsigned int port)
00100 {
00101 int r;
00102 if (sock != NULL) delete sock;
00103 sock = new Socket(hostname,port);
00104 if (verbose)
00105 sock->showErrors();
00106 else
00107 sock->hideErrors();
00108 if (!sock->Open()) goto clean_exit;
00109 if (!sendInitSeq()) goto clean_exit;
00110
00111 terminate = false;
00112 r = pthread_create(&in_thread,NULL,commmanager_inthread,this);
00113 if (r != 0) throw XString("Failed to start CommManager thread: ") + strerror(errno);
00114
00115 return true;
00116
00117
00118 clean_exit:
00119 delete sock;
00120 sock = NULL;
00121 return false;
00122 }
00123
00124 void CommManager::setVerboseLevel(unsigned int v) {
00125 verbose=v;
00126 if (sock != NULL) {
00127 if (verbose)
00128 sock->showErrors();
00129 else
00130 sock->hideErrors();
00131 }
00132 Q.setVerboseLevel(verbose);
00133 if (verbose > 1)
00134 printf("CommManager: Setting verbose level to %d\n",verbose);
00135 }
00136
00137 bool CommManager::reconnect()
00138 {
00139 if (sock == NULL) {
00140 return false;
00141 }
00142
00143 if (verbose > 0)
00144 printf("CM: reconnecting\n");
00145 sock->Close();
00146 bool ret = sock->Open();;
00147
00148 if (ret) ret = sendInitSeq();
00149 return ret;
00150 }
00151
00152 bool CommManager::close()
00153 {
00154 terminate = true;
00155 if (in_thread != 0) {
00156 pthread_join(in_thread,NULL);
00157 in_thread = 0;
00158 }
00159 if (sock != NULL) {
00160 sock->Close();
00161 delete sock;
00162 }
00163 sock = NULL;
00164 return true;
00165 }
00166
00167 void CommManager::run()
00168 {
00169 if (verbose>1)
00170 printf("T %08X CommManager::run()\n",(int)pthread_self());
00171 Datagram dgm;
00172 if (sock == NULL) return;
00173 if (!sock->IsOpen()) return;
00174 while (!terminate) {
00175 if (!sock->IsOpen()) {
00176 usleep(10000);
00177 continue;
00178 }
00179 if (sock->IsBroken()) {
00180 reconnect();
00181 }
00182 #if 0
00183 printf("T %08X CommManager::run()\n",(int)pthread_self());
00184 struct timespec ts;
00185 clock_gettime(CLOCK_REALTIME, &ts);
00186 printf("Current time is %d.%d\n",(int)ts.tv_sec,(int)ts.tv_nsec);
00187 #endif
00188 if (!sock->WaitData(100)) {
00189 usleep(10000);
00190 continue;
00191 }
00192 if (!dgm.receive(sock,100,(verbose>1))) {
00193 usleep(10000);
00194 continue;
00195 }
00196 if (verbose > 1) {
00197 printf("Received: ");dgm.print(stdout);
00198 }
00199 Q.storeDgm(dgm);
00200 }
00201 if (verbose>1)
00202 printf("CommManager::run exiting\n");
00203 }
00204
00205 bool CommManager::send(Datagram & dgm)
00206 {
00207 if (sock == NULL) return false;
00208 if (!sock->IsOpen()) return false;
00209 if (sock->IsBroken()) { return false; }
00210
00211 pthread_mutex_lock(&sockmtx);
00212
00213 bool res = dgm.send(sock);
00214 if (verbose > 1) {
00215 printf("Sent : ");dgm.print(stdout);
00216 }
00217 pthread_mutex_unlock(&sockmtx);
00218 return res;
00219 }
00220
00221 bool CommManager::addToReceptionField(unsigned char id)
00222 {
00223 Q.addInteresting(id);
00224 return true;
00225 }
00226
00227 bool CommManager::removeFromReceptionField(unsigned char id)
00228 {
00229 Q.remInteresting(id);
00230 return true;
00231 }
00232
00233 bool CommManager::resetReceptionField()
00234 {
00235 Q.resetInteresting();
00236 return true;
00237 }
00238
00239 bool CommManager::wait(unsigned char id, Datagram & dgm, double timeout)
00240 {
00241 return Q.waitDgm(id,dgm,timeout);
00242
00243 }
00244
00245
00246
00247
00248