bcap_server.c
Go to the documentation of this file.
00001 
00025 #include "stdint.h"
00026 #include <stdlib.h>
00027 #include <string.h>
00028 
00029 #if defined(_USE_WIN_API)
00030 #include <process.h>
00031 #include <winsock2.h>
00032 #pragma comment(lib, "wsock32.lib")
00033 #elif defined(_USE_LINUX_API)
00034 #include <arpa/inet.h>
00035 #include <errno.h>
00036 #include <pthread.h>
00037 #include <termios.h>
00038 #else
00039 #include "dn_additional.h"
00040 #endif
00041 
00042 #include "dn_common.h"
00043 #include "dn_device.h"
00044 #include "dn_tcp.h"
00045 #include "dn_udp.h"
00046 #include "dn_com.h"
00047 #include "dn_thread.h"
00048 #include "bcap_common.h"
00049 #include "bcap_mapid.h"
00050 #include "bcap_server.h"
00051 
00056 #define _BCAP_SERVER_MAX (BCAP_TCP_MAX + BCAP_UDP_MAX + BCAP_COM_MAX)
00057 
00062 #define _FUNCTION_ID_MAX (137 + 1)
00063 
00068 enum CHANGE_RELATION
00069 {
00070   ADD_CHILD,    
00071   DELETE_CHILD, 
00072   DESTROY_SELF, 
00073 };
00074 
00079 struct VEC_OBJECT
00080 {
00081   int32_t id;              
00082   uint32_t hObj;           
00083   struct VEC_OBJECT *prev; 
00084   struct VEC_OBJECT *next; 
00085 };
00086 
00091 struct CONN_BCAP_SERVER
00092 {
00093   struct CONN_PARAM_COMMON device; 
00094   struct BCAP_PACKET last_send;    
00095   struct BCAP_PACKET last_recv;    
00096   uint32_t exec_timeout;           
00097   uint32_t wdt_interval;           
00098   uint32_t last_modified;          
00099   THREAD main_thread;              
00100   THREAD sub_thread;               
00101   EVENT term_main_evt;             
00102   EVENT term_sub_evt;              
00103   EVENT exec_evt;                  
00104   EVENT comp_evt;                  
00105   int num_object;                  
00106   struct VEC_OBJECT *stack;        
00107   int num_child;                   
00108   MUTEX *relation_mutex;           
00109   struct CONN_BCAP_SERVER *parent; 
00110   struct CONN_BCAP_SERVER *node1;  
00111   struct CONN_BCAP_SERVER *node2;  
00112 };
00113 
00114 static CALL_FUNC_BCAP m_list_func[_FUNCTION_ID_MAX];
00115 static struct CONN_BCAP_SERVER m_conn_param[_BCAP_SERVER_MAX];
00116 
00117 static THRET THTYPE
00118 recv_thread(void *arg);
00119 
00126 static int
00127 find_open_address(int type)
00128 {
00129   int i, start, end, index = -1;
00130 
00131   switch(type) {
00132     case CONN_TCP:
00133       start = 0;
00134       end = BCAP_TCP_MAX;
00135       break;
00136     case CONN_UDP:
00137       start = BCAP_TCP_MAX;
00138       end = start + BCAP_UDP_MAX;
00139       break;
00140     case CONN_COM:
00141       start = BCAP_TCP_MAX + BCAP_UDP_MAX;
00142       end = start + BCAP_COM_MAX;
00143       break;
00144     default:
00145       return 0;
00146   }
00147 
00148   for(i = start; i < end; i++) {
00149     if(m_conn_param[i].device.sock == 0) {
00150       index = i;
00151       break;
00152     }
00153   }
00154 
00155   return (index + 1);
00156 }
00157 
00164 static struct CONN_BCAP_SERVER*
00165 check_address(int index)
00166 {
00167   index--;
00168 
00169   if(index < 0 || _BCAP_SERVER_MAX <= index) {
00170     return NULL;
00171   }
00172   else if(m_conn_param[index].device.sock == 0) {
00173     return NULL;
00174   }
00175 
00176   return &m_conn_param[index];
00177 }
00178 
00185 static HRESULT
00186 push_vector(struct CONN_BCAP_SERVER *bcap_param, struct VEC_OBJECT *pObj)
00187 {
00188   struct VEC_OBJECT *pPrev;
00189 
00190   if(bcap_param->num_object >= BCAP_OBJECT_MAX) {
00191     return E_MAX_OBJECT;
00192   }
00193 
00194   /* Replaces the created object to top of vector */
00195   pPrev = bcap_param->stack;
00196   bcap_param->stack = pObj;
00197 
00198   /* Sets relation */
00199   pObj->prev = pPrev;
00200   if(pPrev != NULL) {
00201     pPrev->next = pObj;
00202   }
00203 
00204   bcap_param->num_object++;
00205 
00206   return S_OK;
00207 }
00208 
00216 static HRESULT
00217 pop_vector(struct CONN_BCAP_SERVER *bcap_param, struct VEC_OBJECT **pObj,
00218     int index)
00219 {
00220   int i;
00221   struct VEC_OBJECT *pPrev, *pNext, *pCur = bcap_param->stack;
00222   HRESULT hr = E_HANDLE;
00223 
00224   for(i = 0; (i < bcap_param->num_object) && (pCur); i++) {
00225     if(i == index) {
00226       *pObj = pCur;
00227 
00228       /* Gets the object which is later than the poped one */
00229       pNext = pCur->next;
00230       pCur->next = NULL;
00231 
00232       /* Gets the object which is earlier than the poped one */
00233       pPrev = pCur->prev;
00234       pCur->prev = NULL;
00235 
00236       if(pNext == NULL) { // If the target object is the latest one
00237         bcap_param->stack = pPrev;
00238       } else {
00239         pNext->prev = pPrev;
00240       }
00241 
00242       if(pPrev != NULL) { // If the target object is not the earliest one
00243         pPrev->next = pNext;
00244       }
00245 
00246       bcap_param->num_object--;
00247       hr = S_OK;
00248       break;
00249     }
00250 
00251     pCur = pCur->prev;
00252   }
00253 
00254   return hr;
00255 }
00256 
00265 static int
00266 search_vector(struct CONN_BCAP_SERVER *bcap_param, int32_t id, uint32_t hObj)
00267 {
00268   int i, index = -1;
00269   struct VEC_OBJECT *pCur = bcap_param->stack;
00270 
00271   for(i = 0; (i < bcap_param->num_object) && (pCur); i++) {
00272     if((pCur->id == id) && (pCur->hObj == hObj)) {
00273       index = i;
00274       break;
00275     }
00276 
00277     pCur = pCur->prev;
00278   }
00279 
00280   return index;
00281 }
00282 
00290 static struct CONN_BCAP_SERVER *
00291 search_node(struct CONN_BCAP_SERVER *parent, const void *arg, int size)
00292 {
00293   struct CONN_BCAP_SERVER *node = NULL, *tmp;
00294 
00295   tmp = parent->node1;
00296   while(tmp != NULL) {
00297     if(memcmp(tmp->device.arg, arg, size) == 0) {
00298       node = tmp;
00299       break;
00300     }
00301     tmp = tmp->node2;
00302   }
00303 
00304   return node;
00305 }
00306 
00314 static HRESULT
00315 change_relation(struct CONN_BCAP_SERVER *own, int mode, int *sock)
00316 {
00317   HRESULT hr = S_OK;
00318   struct CONN_BCAP_SERVER *node, *tmp;
00319   int flag_mutex;
00320   MUTEX *mutex;
00321 
00322   /* Checks mutex object */
00323   mutex = own->relation_mutex;
00324   flag_mutex = ((mutex != NULL) ? 1 : 0);
00325 
00326   /* Locks mutex and must not returns this function without end of one. */
00327   if(flag_mutex) {
00328     hr = lock_mutex(mutex, INFINITE);
00329     if(FAILED(hr)) return hr;
00330   }
00331 
00332   switch(mode) {
00333     case ADD_CHILD:
00334       /* Root node only */
00335       if(own->parent == NULL) {
00336         /* Creates new node */
00337         node = (struct CONN_BCAP_SERVER *) malloc(
00338             sizeof(struct CONN_BCAP_SERVER));
00339         if(node == NULL) {
00340           hr = E_OUTOFMEMORY;
00341           goto exit_proc;
00342         }
00343 
00344         /* Initializes node memory */
00345         memset(node, 0, sizeof(struct CONN_BCAP_SERVER));
00346 
00347         /* Copies device parameters from parent node */
00348         node->device = own->device;
00349 
00350         /* Sets child socket */
00351         node->device.sock = *sock;
00352 
00353         /* Copies parameters */
00354         node->exec_timeout = own->exec_timeout;
00355         node->wdt_interval = own->wdt_interval;
00356 
00357         /* Sets last modified */
00358         node->last_modified = gettimeofday_msec();
00359 
00360         /* Copies mutex */
00361         node->relation_mutex = own->relation_mutex;
00362 
00363         /* Sets parent node */
00364         node->parent = own;
00365         own->num_child++;
00366 
00367         /* Replaces the head of children */
00368         tmp = own->node1;
00369         own->node1 = node;
00370         node->node2 = tmp;
00371         if(tmp != NULL) tmp->node1 = node;
00372 
00373         if(flag_mutex) {
00374           hr = node->device.dn_set_timeout(*sock, node->device.timeout);
00375           if(FAILED(hr)) {
00376             node->device.dn_close(sock);
00377             free(node);
00378             goto exit_proc;
00379           }
00380 
00381           /* Creates terminal event for main thread */
00382           hr = create_event(&node->term_main_evt, 1, 0);
00383           if(FAILED(hr)) {
00384             node->device.dn_close(sock);
00385             free(node);
00386             goto exit_proc;
00387           }
00388 
00389           /* Begins child thread */
00390           begin_thread(&node->main_thread, &recv_thread, node);
00391         } else {
00392           switch(node->device.type) {
00393             case CONN_UDP:
00394               node->device.arg = malloc(sizeof(struct sockaddr_in));
00395               memcpy(node->device.arg, own->device.arg, sizeof(struct sockaddr_in));
00396               break;
00397             default:
00398               break;
00399           }
00400 
00401           node->last_send.args =
00402               (VARIANT*) malloc(sizeof(VARIANT));
00403           VariantInit(node->last_send.args);
00404         }
00405       }
00406       break;
00407 
00408     case DELETE_CHILD:
00409       /* Root node only */
00410       if(own->parent == NULL) {
00411         node = own->node2;
00412         while (node != NULL) {
00413           tmp = node->node2;
00414 
00415           if(flag_mutex) {
00416             /* Ends child thread */
00417             set_event(&node->term_main_evt);
00418             exit_thread(node->main_thread);
00419 
00420             /* Destroys event */
00421             destroy_event(&node->term_main_evt);
00422 
00423             /* Closes connection */
00424             node->device.dn_close(&node->device.sock);
00425           } else {
00426             VariantClear(node->last_send.args);
00427             free(node->last_send.args);
00428 
00429             if(node->device.arg != NULL) {
00430                 free(node->device.arg);
00431             }
00432           }
00433 
00434           free(node);
00435           node = tmp;
00436 
00437           own->num_child--;
00438         }
00439         own->node2 = NULL;
00440       }
00441       break;
00442 
00443     case DESTROY_SELF:
00444       if(own->parent != NULL) {
00445         /* Removes own node from the children list */
00446         tmp = own->node1;
00447 
00448         if(tmp == NULL) { // If own node is the youngest children
00449           own->parent->node1 = own->node2;
00450         } else {
00451           tmp->node2 = own->node2;
00452         }
00453 
00454         if(own->node2 != NULL) { // If own node is not the oldest children
00455           own->node2->node1 = tmp;
00456         }
00457 
00458         /* Adds own node to the parent's delete */
00459         tmp = own->parent->node2;
00460         own->parent->node2 = own;
00461         own->node2 = tmp;
00462         if(tmp != NULL) tmp->node1 = own;
00463       } else {
00464         if(!flag_mutex) {
00465             node = own->node1;
00466             while(node != NULL) {
00467               tmp = node->node2;
00468               change_relation(node, DESTROY_SELF, NULL);
00469               node = tmp;
00470             }
00471             change_relation(own, DELETE_CHILD, NULL);
00472         }
00473       }
00474       break;
00475 
00476     default:
00477       hr = E_INVALIDARG;
00478       break;
00479   }
00480 
00481 exit_proc:
00482   if(flag_mutex) {
00483     unlock_mutex(mutex);
00484   }
00485 
00486   return hr;
00487 }
00488 
00494 static int
00495 check_lifelimit(struct CONN_BCAP_SERVER *parent)
00496 {
00497   uint32_t cur, diff;
00498   struct CONN_BCAP_SERVER *child, *tmp;
00499 
00500   child = parent->node1;
00501   while(child != NULL) {
00502     tmp = child->node2;
00503 
00504     cur = gettimeofday_msec();
00505     diff = calc_time_diff(child->last_modified, cur);
00506     if(diff > UDP_LIFELIMIT) {
00507       change_relation(child, DESTROY_SELF, NULL);
00508     }
00509 
00510     child = tmp;
00511   }
00512 
00513   change_relation(parent, DELETE_CHILD, NULL);
00514 
00515   return parent->num_child;
00516 }
00517 
00524 static HRESULT
00525 bcap_callfunc(struct BCAP_PACKET *recv_packet, struct BCAP_PACKET *send_packet)
00526 {
00527   int32_t id;
00528   CALL_FUNC_BCAP func;
00529 
00530   /* Initializes send packet */
00531   send_packet->serial = recv_packet->serial;
00532   send_packet->reserv = 0;
00533   send_packet->id = E_INVALIDARG;
00534   send_packet->argc = 0;
00535 
00536   id = recv_packet->id;
00537   if((0 < id) && (id < _FUNCTION_ID_MAX)) {
00538     func = m_list_func[id];
00539     if(func == NULL) {
00540       /* The function is not implemented */
00541       send_packet->id = E_NOTIMPL;
00542     } else {
00543       /* callback function */
00544       VariantClear(send_packet->args);
00545       send_packet->id = func(recv_packet->args, recv_packet->argc,
00546           send_packet->args);
00547       send_packet->argc = m_map_id[id].return_flag ? 1 : 0;
00548     }
00549   }
00550 
00551   return S_OK;
00552 }
00553 
00559 static HRESULT
00560 receive_execute(struct CONN_BCAP_SERVER *bcap_param)
00561 {
00562   int index;
00563   int32_t relation_id;
00564   uint16_t i, clear_flag = 1;
00565   uint32_t cur, start, diff;
00566   HRESULT hr;
00567   struct CONN_BCAP_SERVER *tmp_param = bcap_param;
00568   struct CONN_PARAM_COMMON *device = &bcap_param->device;
00569   struct BCAP_PACKET tmp_send_packet, tmp_recv_packet, *send_packet =
00570       &bcap_param->last_send, *recv_packet = &bcap_param->last_recv;
00571   struct VEC_OBJECT *pObj = NULL;
00572   BSTR bstrOpt = NULL;
00573   VARIANT vntTmp, vntOpt;
00574 
00575   VariantInit(&vntTmp);
00576   VariantInit(&vntOpt);
00577 
00578   /* Initializes temporary packet */
00579   tmp_recv_packet.argc = (uint16_t) -1;
00580   tmp_recv_packet.args = NULL;
00581 
00582   /* Receives b-CAP packet */
00583   hr = bcap_recv(device, &tmp_recv_packet, 0);
00584 
00585   if(SUCCEEDED(hr)) {
00586     /* Sets S_EXECUTING packet */
00587     memset(&tmp_send_packet, 0, sizeof(struct BCAP_PACKET));
00588     tmp_send_packet.serial = tmp_recv_packet.serial;
00589     tmp_send_packet.id = S_EXECUTING;
00590 
00591     /* Checks retry packet */
00592     switch(device->type) {
00593       case CONN_UDP:
00594         tmp_param = search_node(bcap_param, device->arg,
00595             sizeof(struct sockaddr_in));
00596         if(tmp_param == NULL) {
00597           /* Checks life limit */
00598           if((bcap_param->num_child >= BCAP_CLIENT_MAX)
00599               && (check_lifelimit(bcap_param) >= BCAP_CLIENT_MAX))
00600           {
00601             tmp_send_packet.id = E_MAX_CONNECT;
00602             bcap_send(device, &tmp_send_packet);
00603             hr = S_FALSE;
00604             goto exit_proc;
00605           }
00606 
00607           /* Adds child */
00608           change_relation(bcap_param, ADD_CHILD, &device->sock);
00609           tmp_param = bcap_param->node1;
00610         }
00611 
00612         send_packet = &tmp_param->last_send;
00613 
00614         //break;
00615 
00616       case CONN_COM:
00617         /* Sets retry count */
00618         tmp_recv_packet.reserv =
00619             (tmp_recv_packet.reserv == 0) ?
00620                 tmp_recv_packet.serial : tmp_recv_packet.reserv;
00621 
00622         /* If already responded, then does not execute */
00623         if(send_packet->serial == tmp_recv_packet.reserv) {
00624           /* Copies last send packet */
00625           tmp_send_packet = *send_packet;
00626 
00627           /* Sets new serial number */
00628           tmp_send_packet.serial = tmp_recv_packet.serial;
00629 
00630           /* Sends temporary send packet */
00631           bcap_send(device, &tmp_send_packet);
00632           hr = S_FALSE;
00633           goto exit_proc;
00634         }  
00635 
00636         break;
00637 
00638       default:
00639         break;
00640     }
00641 
00642     /* Checks execute thread */
00643     hr = wait_event(&bcap_param->comp_evt, 0);
00644     if(hr == E_TIMEOUT) {
00645       /* Sends result busy process */
00646       tmp_send_packet.id = E_BUSY_PROC;
00647       bcap_send(device, &tmp_send_packet);
00648       goto exit_proc;
00649     }
00650 
00651     switch(tmp_recv_packet.id) {
00652       case ID_SERVICE_START:
00653       case ID_CONTROLLER_CONNECT:
00654       case ID_CONTROLLER_GETEXTENSION:
00655       case ID_CONTROLLER_GETFILE:
00656       case ID_FILE_GETFILE:
00657       case ID_CONTROLLER_GETROBOT:
00658       case ID_CONTROLLER_GETTASK:
00659       case ID_CONTROLLER_GETVARIABLE:
00660       case ID_EXTENSION_GETVARIABLE:
00661       case ID_FILE_GETVARIABLE:
00662       case ID_ROBOT_GETVARIABLE:
00663       case ID_TASK_GETVARIABLE:
00664       case ID_CONTROLLER_GETCOMMAND:
00665       case ID_CONTROLLER_GETMESSAGE:
00666         if(bcap_param->num_object >= BCAP_OBJECT_MAX) {
00667           tmp_send_packet.id = E_MAX_OBJECT;
00668           bcap_send(device, &tmp_send_packet);
00669           hr = S_FALSE;
00670           goto exit_proc;
00671         }
00672 
00673         if(tmp_recv_packet.id == ID_SERVICE_START) {
00674           if((tmp_recv_packet.argc >= 1) && (tmp_recv_packet.args != NULL)) {
00675             VariantCopy(&vntTmp, &tmp_recv_packet.args[0]);
00676             hr = VariantChangeType(&vntTmp, &vntTmp, 0, VT_BSTR);
00677             if(FAILED(hr)) {
00678               tmp_send_packet.id = hr;
00679               bcap_send(device, &tmp_send_packet);
00680               hr = S_FALSE;
00681               goto exit_proc;
00682             }
00683           } else {
00684             vntTmp.vt = VT_BSTR;
00685             vntTmp.bstrVal = SysAllocString(L"");
00686           }
00687 
00688           bstrOpt = SysAllocString(L"WDT");
00689           hr = GetOptionValue(vntTmp.bstrVal, bstrOpt, VT_UI4, &vntOpt);
00690           vntOpt.ulVal =
00691               (vntOpt.vt == VT_UI4) ? vntOpt.ulVal : INIT_WDT_INTERVAL;
00692           if(vntOpt.ulVal < MIN_WDT_INTERVAL) {
00693             tmp_send_packet.id = E_INVALIDARG;
00694             bcap_send(device, &tmp_send_packet);
00695             hr = S_FALSE;
00696             goto exit_proc;
00697           } else {
00698             tmp_param->wdt_interval = vntOpt.ulVal;
00699           }
00700           SysFreeString(bstrOpt);
00701           VariantClear(&vntOpt);
00702 
00703           bstrOpt = SysAllocString(L"InvokeTimeout");
00704           hr = GetOptionValue(vntTmp.bstrVal, bstrOpt, VT_UI4, &vntOpt);
00705           vntOpt.ulVal =
00706               (vntOpt.vt == VT_UI4) ? vntOpt.ulVal : INIT_EXEC_TIMEOUT;
00707           if(vntOpt.ulVal < MIN_WDT_INTERVAL) {
00708             tmp_send_packet.id = E_INVALIDARG;
00709             bcap_send(device, &tmp_send_packet);
00710             hr = S_FALSE;
00711             goto exit_proc;
00712           } else {
00713             tmp_param->exec_timeout = vntOpt.ulVal;
00714           }
00715           SysFreeString(bstrOpt);
00716           VariantClear(&vntOpt);
00717 
00718           VariantClear(&vntTmp);
00719           bstrOpt = NULL;
00720         }
00721 
00722         break;
00723 
00724       default:
00725         break;
00726     }
00727 
00728     /* Resets last received packet */
00729     if(recv_packet->args != NULL) {
00730       for(i = 0; i < recv_packet->argc; i++) {
00731         VariantClear(&recv_packet->args[i]);
00732       }
00733       free(recv_packet->args);
00734     }
00735 
00736     /* Copies to last receive packet */
00737     clear_flag = 0;
00738     *recv_packet = tmp_recv_packet;
00739 
00740     /* Runs execute thread */
00741     reset_event(&bcap_param->comp_evt);
00742     set_event(&bcap_param->exec_evt);
00743 
00744     if(SUCCEEDED(hr)) {
00745       start = gettimeofday_msec();
00746       while(1) {
00747         hr = wait_event(&bcap_param->comp_evt, tmp_param->wdt_interval);
00748         if(SUCCEEDED(hr)) {
00749           break;
00750         } else {
00751           /* Sends S_EXECUTING packet */
00752           hr = bcap_send(device, &tmp_send_packet);
00753           if(FAILED(hr)) {
00754             break;
00755           }
00756         }
00757 
00758         /* Checks executing timeout */
00759         cur = gettimeofday_msec();
00760         diff = calc_time_diff(start, cur);
00761         if(diff > tmp_param->exec_timeout) {
00762           hr = E_TIMEOUT;
00763           break;
00764         }
00765       }
00766     }
00767   }
00768 
00769 exit_proc:
00770   if(hr == S_OK) {
00771     if(bcap_param->last_send.id == S_OK) {
00772       /* Changes the vector of created objects */
00773       relation_id = m_map_id[recv_packet->id].relation_id;
00774       if(relation_id > 0) { // Push
00775         pObj = (struct VEC_OBJECT *) malloc(sizeof(struct VEC_OBJECT));
00776         if(pObj != NULL) {
00777           memset(pObj, 0, sizeof(struct VEC_OBJECT));
00778           pObj->id = relation_id;
00779           pObj->hObj =
00780               (recv_packet->id == ID_SERVICE_START) ?
00781                   0 : bcap_param->last_send.args[0].lVal;
00782           push_vector(bcap_param, pObj);
00783         }
00784       }
00785       else if(relation_id < 0) { // Pop
00786         index = search_vector(bcap_param, recv_packet->id,
00787           (recv_packet->id == ID_SERVICE_STOP) ?
00788               0 : recv_packet->args[0].lVal);
00789         if(index >= 0) {
00790           pop_vector(bcap_param, &pObj, index);
00791           free(pObj);
00792         }
00793         if((device->type == CONN_UDP)
00794           && (recv_packet->id == ID_SERVICE_STOP))
00795         {
00796           change_relation(tmp_param, DESTROY_SELF, NULL);
00797           change_relation(bcap_param, DELETE_CHILD, NULL);
00798           tmp_param = NULL;
00799         }
00800       }
00801     }
00802 
00803     /* Responds the result message */
00804     hr = bcap_send(device, &bcap_param->last_send);
00805     if(SUCCEEDED(hr) && (tmp_param != NULL)) {
00806         tmp_param->last_send.serial = bcap_param->last_send.serial;
00807         tmp_param->last_send.reserv = bcap_param->last_send.reserv;
00808         tmp_param->last_send.id     = bcap_param->last_send.id;
00809         tmp_param->last_send.argc   = bcap_param->last_send.argc;
00810         VariantCopy(tmp_param->last_send.args, bcap_param->last_send.args);
00811 
00812         tmp_param->last_modified = gettimeofday_msec();
00813     }
00814   }
00815 
00816   /* Clears temporary packet */
00817   if(clear_flag) {
00818     if(tmp_recv_packet.args != NULL) {
00819       for(i = 0; i < tmp_recv_packet.argc; i++) {
00820         VariantClear(&tmp_recv_packet.args[i]);
00821       }
00822       free(tmp_recv_packet.args);
00823     }
00824   }
00825 
00826   VariantClear(&vntTmp);
00827   VariantClear(&vntOpt);
00828   if(bstrOpt) {
00829     SysFreeString(bstrOpt);
00830   }
00831 
00832   return hr;
00833 }
00834 
00840 static THRET THTYPE
00841 exec_thread(void *arg)
00842 {
00843 #if !defined(THRET)
00844   THRET ret = (THRET)NULL;
00845 #endif
00846 
00847   HRESULT hr;
00848   struct CONN_BCAP_SERVER *bcap_param = (struct CONN_BCAP_SERVER *) arg;
00849   EVENT *evt[2] =
00850     { &bcap_param->exec_evt, &bcap_param->term_sub_evt };
00851 
00852   while(1) {
00853     hr = wait_event_multi(evt, 2, INFINITE, 0);
00854     if(hr == WAIT_OBJECT_0 + 1) {
00855       break;
00856     }
00857     else if(hr == WAIT_OBJECT_0) {
00858       bcap_callfunc(&bcap_param->last_recv, &bcap_param->last_send);
00859     }
00860     else {
00861       bcap_param->last_send.serial = bcap_param->last_recv.serial;
00862       bcap_param->last_send.reserv = 0;
00863       bcap_param->last_send.id = hr;
00864       bcap_param->last_send.argc = 0;
00865     }
00866     set_event(&bcap_param->comp_evt);
00867   }
00868 
00869 #if !defined(THRET)
00870   return ret;
00871 #endif
00872 }
00873 
00879 static THRET THTYPE
00880 recv_thread(void *arg)
00881 {
00882 #if !defined(THRET)
00883   THRET ret = (THRET)NULL;
00884 #endif
00885 
00886   uint16_t i;
00887   HRESULT hr;
00888   struct CONN_BCAP_SERVER *bcap_param = (struct CONN_BCAP_SERVER *) arg;
00889   struct BCAP_PACKET *send_packet = &bcap_param->last_send, *recv_packet =
00890       &bcap_param->last_recv;
00891   struct VEC_OBJECT *pObj = NULL;
00892   VARIANT vnt_send, vntTmp;
00893   CALL_FUNC_BCAP func;
00894 
00895   /* Sets last send packet */
00896   send_packet->args = &vnt_send;
00897   VariantInit(&vnt_send);
00898 
00899   /* Creates terminal event for sub thread */
00900   hr = create_event(&bcap_param->term_sub_evt, 1, 0);
00901   if(FAILED(hr)) goto exit_proc;
00902 
00903   /* Creates events for synchronizing threads */
00904   hr = create_event(&bcap_param->exec_evt, 0, 0);
00905   if(FAILED(hr)) goto exit_proc;
00906 
00907   hr = create_event(&bcap_param->comp_evt, 1, 1);
00908   if(FAILED(hr)) goto exit_proc;
00909 
00910   /* Begins sub thread */
00911   begin_thread(&bcap_param->sub_thread, &exec_thread, arg);
00912 
00913   while(1) {
00914     hr = wait_event(&bcap_param->term_main_evt, 0);
00915     if(SUCCEEDED(hr)) {
00916       break;
00917     }
00918 
00919     hr = receive_execute(bcap_param);
00920     if(FAILED(hr) && hr != E_TIMEOUT) {
00921       break;
00922     }
00923   }
00924 
00925 exit_proc:
00926   /* Ends sub thread */
00927   set_event(&bcap_param->term_sub_evt);
00928   exit_thread(bcap_param->sub_thread);
00929 
00930   /* Destroys events */
00931   destroy_event(&bcap_param->term_sub_evt);
00932   destroy_event(&bcap_param->exec_evt);
00933   destroy_event(&bcap_param->comp_evt);
00934 
00935   /* Clears last send packet */
00936   VariantClear(&vnt_send);
00937 
00938   /* Clears last received packet */
00939   if(recv_packet->args != NULL) {
00940     for(i = 0; i < recv_packet->argc; i++) {
00941       VariantClear(&recv_packet->args[i]);
00942     }
00943     free(recv_packet->args);
00944   }
00945 
00946   /* Release all of vector elements */
00947   VariantInit(&vntTmp);
00948   vntTmp.vt = VT_I4;
00949 
00950   while(1) {
00951     hr = pop_vector(bcap_param, &pObj, 0);
00952     if(FAILED(hr)) break;
00953 
00954     func = m_list_func[pObj->id];
00955     if(func != NULL) {
00956       vntTmp.lVal = pObj->hObj;
00957       func(&vntTmp, ((pObj->id == ID_SERVICE_STOP) ? 0 : 1), &vnt_send);
00958       VariantClear(&vnt_send);
00959     }
00960 
00961     free(pObj);
00962   }
00963 
00964   VariantClear(&vntTmp);
00965 
00966   /* Destroys self */
00967   change_relation(bcap_param, DESTROY_SELF, NULL);
00968 
00969 #if !defined(THRET)
00970   return ret;
00971 #endif
00972 }
00973 
00979 static THRET THTYPE
00980 accept_thread(void *arg)
00981 {
00982 #if !defined(THRET)
00983   THRET ret = (THRET)NULL;
00984 #endif
00985 
00986   int client;
00987   HRESULT hr;
00988   volatile struct CONN_BCAP_SERVER *child;
00989   struct CONN_BCAP_SERVER *bcap_param = (struct CONN_BCAP_SERVER *) arg;
00990   MUTEX mutex;
00991 
00992   /* Initializes mutex */
00993   bcap_param->relation_mutex = &mutex;
00994   hr = initialize_mutex(&mutex);
00995   if(FAILED(hr)) goto exit_proc;
00996 
00997   while(1) {
00998     hr = wait_event(&bcap_param->term_main_evt, 300);
00999     if(SUCCEEDED(hr)) {
01000       break;
01001     }
01002 
01003     if(bcap_param->num_child < BCAP_CLIENT_MAX) {
01004       hr = tcp_accept(bcap_param->device.sock, &client);
01005       if(SUCCEEDED(hr)) {
01006         /* Sets no delay option */
01007         tcp_set_nodelay(client, 1);
01008 
01009         /* Sets keep alive option */
01010         tcp_set_keepalive(client, KEEPALIVE_ENABLE, KEEPALIVE_IDLE,
01011             KEEPALIVE_INTERVAL, KEEPALIVE_COUNT);
01012 
01013         /* Adds child */
01014         change_relation(bcap_param, ADD_CHILD, &client);
01015       }
01016     }
01017 
01018     /* Deletes child */
01019     change_relation(bcap_param, DELETE_CHILD, NULL);
01020   }
01021 
01022 exit_proc:
01023   /* Ends all children thread */
01024   child = bcap_param->node1;
01025   while(child != NULL) {
01026     set_event((EVENT *) &child->term_main_evt);
01027     exit_thread(child->main_thread);
01028 
01029     child = bcap_param->node1;
01030   }
01031 
01032   /* Deletes child */
01033   change_relation(bcap_param, DELETE_CHILD, NULL);
01034 
01035   /* Releases mutex */
01036   release_mutex(&mutex);
01037 
01038 #if !defined(THRET)
01039   return ret;
01040 #endif
01041 }
01042 
01043 HRESULT
01044 bCap_SetCallFunc(int32_t id, CALL_FUNC_BCAP func)
01045 {
01046   if((id <= 0) || (_FUNCTION_ID_MAX <= id)) {
01047     return E_INVALIDARG;
01048   }
01049 
01050   m_list_func[id] = func;
01051 
01052   return S_OK;
01053 }
01054 
01055 HRESULT
01056 bCap_Open_Server(const char *connect, uint32_t timeout, int *pfd)
01057 {
01058   int type, index, *sock;
01059   HRESULT hr;
01060   void *conn_param;
01061   struct CONN_PARAM_ETH eth_param =
01062     { 0, 0, htonl(INADDR_ANY), htons(5007) };
01063   struct CONN_PARAM_COM com_param =
01064     { 1, 38400, NOPARITY, 8, ONESTOPBIT, 0 };
01065   struct CONN_BCAP_SERVER *bcap_param;
01066   struct CONN_PARAM_COMMON *device;
01067   struct sockaddr_in *paddr;
01068 
01069   if(connect == NULL || pfd == NULL)
01070     return E_INVALIDARG;
01071 
01072   type = parse_conn_type(connect);
01073 
01074   index = find_open_address(type);
01075   if(index == 0)
01076     return E_MAX_OBJECT;
01077 
01078   bcap_param = &m_conn_param[index - 1];
01079   device = &bcap_param->device;
01080 
01081   /* Initializes connection parameters */
01082   device->type = type;
01083   switch(device->type) {
01084     case CONN_TCP:
01085       hr = parse_conn_param_ether(connect, &eth_param);
01086       conn_param = &eth_param;
01087       device->arg = NULL;
01088       device->dn_open = &tcp_open_server;
01089       device->dn_close = &tcp_close;
01090       device->dn_send = &tcp_send;
01091       device->dn_recv = &tcp_recv;
01092       device->dn_set_timeout = &tcp_set_timeout;
01093       break;
01094     case CONN_UDP:
01095       hr = parse_conn_param_ether(connect, &eth_param);
01096       conn_param = &eth_param;
01097       paddr = (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in));
01098       if(paddr == NULL) {
01099         hr = E_OUTOFMEMORY;
01100         break;
01101       }
01102       paddr->sin_addr.s_addr = eth_param.dst_addr;
01103       paddr->sin_port = eth_param.dst_port;
01104       paddr->sin_family = AF_INET;
01105       device->arg = (void *) paddr;
01106       device->dn_open = &udp_open;
01107       device->dn_close = &udp_close;
01108       device->dn_send = &udp_send;
01109       device->dn_recv = &udp_recv;
01110       device->dn_set_timeout = &udp_set_timeout;
01111       break;
01112     case CONN_COM:
01113       hr = parse_conn_param_serial(connect, &com_param);
01114       conn_param = &com_param;
01115       device->arg = NULL;
01116       device->dn_open = &com_open;
01117       device->dn_close = &com_close;
01118       device->dn_send = &com_send;
01119       device->dn_recv = &com_recv;
01120       device->dn_set_timeout = &com_set_timeout;
01121       break;
01122     default:
01123       hr = E_INVALIDARG;
01124       break;
01125   }
01126 
01127   if(FAILED(hr)) {
01128     if(device->arg != NULL) {
01129       free(device->arg);
01130       device->arg = NULL;
01131     }
01132     memset(bcap_param, 0, sizeof(struct CONN_BCAP_SERVER));
01133     return hr;
01134   }
01135 
01136   /* Create terminal event for main thread */
01137   hr = create_event(&bcap_param->term_main_evt, 1, 0);
01138   if(FAILED(hr)) {
01139     if(device->arg != NULL) {
01140       free(device->arg);
01141       device->arg = NULL;
01142     }
01143     memset(bcap_param, 0, sizeof(struct CONN_BCAP_SERVER));
01144     return hr;
01145   }
01146 
01147   /* Opens connection */
01148   sock = &device->sock;
01149   hr = device->dn_open(conn_param, sock);
01150   if(FAILED(hr)) {
01151     destroy_event(&bcap_param->term_main_evt);
01152     if(device->arg != NULL) {
01153       free(device->arg);
01154       device->arg = NULL;
01155     }
01156     memset(bcap_param, 0, sizeof(struct CONN_BCAP_SERVER));
01157     return hr;
01158   }
01159 
01160   hr = device->dn_set_timeout(*sock, timeout);
01161   if(FAILED(hr)) {
01162     bCap_Close_Server(&index);
01163     return hr;
01164   }
01165 
01166   /* Sets parameters */
01167   device->timeout = timeout;
01168   bcap_param->exec_timeout   = INIT_EXEC_TIMEOUT;
01169   bcap_param->wdt_interval   = INIT_WDT_INTERVAL;
01170 
01171   /* Begins main thread */
01172   if(device->type == CONN_TCP) {
01173     begin_thread(&bcap_param->main_thread, &accept_thread, bcap_param);
01174   } else {
01175     begin_thread(&bcap_param->main_thread, &recv_thread, bcap_param);
01176   }
01177 
01178   *pfd = index;
01179 
01180   return S_OK;
01181 }
01182 
01183 HRESULT
01184 bCap_Close_Server(int *pfd)
01185 {
01186   int index, *sock;
01187   struct CONN_BCAP_SERVER *bcap_param;
01188   struct CONN_PARAM_COMMON *device;
01189 
01190   if(pfd == NULL)
01191     return E_HANDLE;
01192 
01193   index = *pfd;
01194 
01195   bcap_param = check_address(index);
01196   if(bcap_param == NULL)
01197     return E_HANDLE;
01198 
01199   device = &bcap_param->device;
01200   sock = &device->sock;
01201 
01202   /* Ends main thread */
01203   set_event(&bcap_param->term_main_evt);
01204   exit_thread(bcap_param->main_thread);
01205 
01206   /* Destroys event */
01207   destroy_event(&bcap_param->term_main_evt);
01208 
01209   /* Closes connection */
01210   device->dn_close(sock);
01211 
01212   /* Releases argument */
01213   if(device->arg != NULL) {
01214     free(device->arg);
01215     device->arg = NULL;
01216   }
01217 
01218   /* Resets connection parameters */
01219   memset(bcap_param, 0, sizeof(struct CONN_BCAP_SERVER));
01220 
01221   *pfd = 0;
01222 
01223   return S_OK;
01224 }


bcap_core
Author(s): DENSO WAVE INCORPORATED
autogenerated on Thu Jun 6 2019 21:00:02