| /**************************************************************************** | |
| * (c) Copyright 2007 Wi-Fi Alliance. All Rights Reserved | |
| * | |
| * | |
| * LICENSE | |
| * | |
| * License is granted only to Wi-Fi Alliance members and designated | |
| * contractors ($B!H(BAuthorized Licensees$B!I(B)..AN Authorized Licensees are granted | |
| * the non-exclusive, worldwide, limited right to use, copy, import, export | |
| * and distribute this software: | |
| * (i) solely for noncommercial applications and solely for testing Wi-Fi | |
| * equipment; and | |
| * (ii) solely for the purpose of embedding the software into Authorized | |
| * Licensee$B!G(Bs proprietary equipment and software products for distribution to | |
| * its customers under a license with at least the same restrictions as | |
| * contained in this License, including, without limitation, the disclaimer of | |
| * warranty and limitation of liability, below..AN The distribution rights | |
| * granted in clause | |
| * (ii), above, include distribution to third party companies who will | |
| * redistribute the Authorized Licensee$B!G(Bs product to their customers with or | |
| * without such third party$B!G(Bs private label. Other than expressly granted | |
| * herein, this License is not transferable or sublicensable, and it does not | |
| * extend to and may not be used with non-Wi-Fi applications..AN Wi-Fi Alliance | |
| * reserves all rights not expressly granted herein..AN | |
| *.AN | |
| * Except as specifically set forth above, commercial derivative works of | |
| * this software or applications that use the Wi-Fi scripts generated by this | |
| * software are NOT AUTHORIZED without specific prior written permission from | |
| * Wi-Fi Alliance. | |
| *.AN | |
| * Non-Commercial derivative works of this software for internal use are | |
| * authorized and are limited by the same restrictions; provided, however, | |
| * that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of | |
| * such derivative works under a perpetual, payment-free license to use, | |
| * modify, and distribute such derivative works for purposes of testing Wi-Fi | |
| * equipment. | |
| *.AN | |
| * Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse | |
| * or promote products that are derived from or that use this software without | |
| * specific prior written permission from Wi-Fi Alliance. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR | |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
| * OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE, | |
| * ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT, | |
| * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| * (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE | |
| * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF | |
| * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ****************************************************************************** | |
| */ | |
| /* | |
| * File: wfa_ca.c | |
| * This is the main program for Control Agent. | |
| * | |
| * Revision History: | |
| * 2006/06/01 -- BETA Release by qhu | |
| * 2006/06/13 -- 00.02 Release by qhu | |
| * 2006/06/30 -- 00.10 Release by qhu | |
| * 2006/07/10 -- 01.00 Release by qhu | |
| * 2006/09/01 -- 01.05 Release by qhu | |
| * 2007/01/11 -- 01.10 released by qhu | |
| * 2007/02/15 -- WMM beta released by qhu, mkaroshi | |
| * 2007/03/21 -- 01.40 WPA2 and Official WMM Beta release by qhu | |
| * 2007/04/20 -- 02.00 WPA2 and Official WMM release by qhu | |
| * 2007/08/15 -- 02.10 WMM-Power Save release by qhu | |
| * 2007/10/10 -- 02.20 Voice SOHO beta -- qhu | |
| * 2007/11/07 -- 02.30 Voice HSO -- qhu | |
| * -- on the calls wfaCtrlSend(), the string len is replaced with strlen() | |
| */ | |
| #include <stdio.h> /* for printf() and fprintf() */ | |
| #include <stdlib.h> /* for atoi() and exit() */ | |
| #include <string.h> | |
| #include "wfa_debug.h" | |
| #include "wfa_main.h" | |
| #include "wfa_types.h" | |
| #include "wfa_tlv.h" | |
| #include "wfa_tg.h" | |
| #include "wfa_cmds.h" | |
| #include "wfa_sock.h" | |
| #include "wfa_miscs.h" | |
| #include "wfa_ca.h" | |
| #include "wfa_agtctrl.h" | |
| #include "wfa_agt.h" | |
| #include "wfa_rsp.h" | |
| #include "wfa_wmmps.h" | |
| #define MAC_ADDR_LEN 18 | |
| #define DEVICE_NAME_LEN 20 | |
| #define TRANSPORT_TYPE_LEN 10 | |
| #define SERVER_IP_LEN 20 | |
| #define INTERFACE_NAME_LEN 31 | |
| #define RESPONSE_SIZE 256 | |
| char gnetIf[WFA_BUFF_32]; /* specify the interface to use */ | |
| int adj_latency; /* adjust sleep time due to latency */ | |
| int isExit = 1; | |
| int gRegSec = 1; /* regularly periodical timeout */ | |
| int gtimeOut = 0; /* timeout value for select call in usec */ | |
| int gSock = -1,xcSockfd = -1, gtgSend, gtgRecv, gtgTransac; | |
| int rwl_wifi_flag = 0; /*Flag to check wheather the transport is wifi */ | |
| BYTE *xcCmdBuf = NULL, *parmsVal = NULL, *trafficBuf = NULL, *respBuf = NULL; | |
| /* stream table */ | |
| tgStream_t *gStreams; | |
| struct timeval *toutvalp; | |
| #ifdef WFA_WMM_EXT | |
| /* | |
| * Thread Synchronize flags | |
| */ | |
| tgWMM_t wmm_thr[WFA_THREADS_NUM]; | |
| extern void *wfa_wmm_thread(void *thr_param); | |
| extern void *wfa_wmmps_thread(); | |
| BOOL gtgStartSync = 0; /* flag to sync End2End Time handshaking */ | |
| BOOL gtgFinishSync = 0; /* flag to sync End2End Time handshaking */ | |
| double min_rttime = 0xFFFFFFFF; | |
| #ifdef WFA_WMM_PS_EXT | |
| BOOL gtgWmmPS = 0; | |
| unsigned long psTxMsg[WFA_BUFF_512]; | |
| unsigned long psRxMsg[WFA_BUFF_512]; | |
| extern int psSockfd ; | |
| extern struct apts_msg apts_msgs[]; | |
| extern void BUILD_APTS_MSG(int msg, unsigned long *txbuf); | |
| extern int wfaWmmPowerSaveProcess(int sockfd); | |
| void *g_wl_handle = NULL; | |
| int wl_set(void *wl, int cmd, void *buf, int len) | |
| { | |
| return 0; | |
| } | |
| #endif /* WFA_WMM_PS_EXT */ | |
| #endif /* WFA_WMM_EXT */ | |
| #ifndef DONE | |
| #define DONE 1 | |
| #endif | |
| extern typeNameStr_t nameLocalStr[]; | |
| /* For integration */ | |
| extern dutCommandRespFuncPtr wfaCmdRespProcFuncTbl[]; | |
| extern void buildDutCommandRespProcessTable(void); | |
| extern typeNameStr_t nameStr[]; | |
| extern char gRespStr[]; | |
| extern sockfd_t gCaSockfd; | |
| extern unsigned short wfa_defined_debug; | |
| extern char* rwl_client_path; | |
| extern xcCommandFuncPtr gWfaCmdFuncTbl[]; /* command process functions */ | |
| extern char gCmdStr[]; | |
| extern dutCmdResponse_t gGenericResp; | |
| extern int clock_drift_ps; | |
| extern int error_check(int errno_defined); | |
| /* | |
| * the output format can be redefined for file output. | |
| */ | |
| int | |
| main(int argc, char *argv[]) | |
| { | |
| char command[WFA_BUFF_1K], respStr[WFA_BUFF_128], cmdName[WFA_BUFF_32]; | |
| char *pcmdStr, *trafficPath; | |
| unsigned short myport; | |
| int maxfdn1 = -1, nfds, i, isFound, DutCmd, nbytes = 0, tag, slen; | |
| int cmdLen = WFA_BUFF_1K, respLen = 0; | |
| int errno_defined; | |
| int length_client_path; | |
| sockfd_t tmsockfd; | |
| BYTE xcCmdBuf[WFA_BUFF_1K], xcCmdTag, pcmdBuf[WFA_BUFF_1K]; | |
| BYTE *respBuf = NULL, *parmsVal = NULL; | |
| FILE* fp = NULL; | |
| fd_set sockSet; | |
| char *rwl_exe_path; | |
| rwl_exe_path = malloc(WFA_BUFF_1K); | |
| /* CA assumes that wl.exe will be stored in the current working directory */ | |
| get_rwl_exe_path(rwl_exe_path, WFA_BUFF_1K); | |
| if (argc < 3) { | |
| DPRINT_ERR(WFA_ERR, "Usage: %s <control agent IP (Win XP)/interface(linux) > <control port no> <--socket/--dongle/--wifi> <serverIp port/clientComport/serverMacaddr>\n", argv[0]); | |
| return 0; | |
| } | |
| /* isdigit() is not working with the build server tagged build | |
| * so isdigit is replaced with isNumber() function call */ | |
| if (isNumber(argv[2]) == FALSE) { | |
| DPRINT_ERR(WFA_ERR, "incorrect port number\n"); | |
| return 0; | |
| } | |
| myport = atoi(argv[2]); | |
| /* interface_validation call checks isString() for linux and | |
| * isIPV4() for win32 OS | |
| */ | |
| if (interface_validation(argv[1]) == FALSE) { | |
| DPRINT_ERR(WFA_ERR, "incorrect network interface\n"); | |
| return 0; | |
| } | |
| if((errno_defined = Start_Socket_Service()) != 0){ | |
| DPRINT_ERR(WFA_ERR, "Start_Socket_Service failed\n"); | |
| return 0; | |
| } | |
| strncpy(gnetIf, argv[1], INTERFACE_NAME_LEN); /* For integration */ | |
| if ((rwl_client_path = malloc(WFA_BUFF_256))== NULL) { | |
| DPRINT_ERR(WFA_ERR, "malloc failed\r\n"); | |
| if((errno_defined = Stop_Socket_Service()) != 0){ | |
| DPRINT_ERR(WFA_ERR, "Stop_Socket_Service failed\n"); | |
| } | |
| return 0; | |
| } | |
| /* get the command line args to get the rwl exe working on different | |
| * transport links - socket/dongle/wifi */ | |
| argv += 3; | |
| strcpy(rwl_client_path, rwl_exe_path); | |
| while (*argv) { | |
| strncat(rwl_client_path, " ", 1); | |
| strncat(rwl_client_path, *argv, strlen(*argv)); | |
| *argv++; | |
| } | |
| length_client_path = strlen(rwl_client_path); | |
| /* Look for wifi transport */ | |
| if(strstr(rwl_client_path, "--wifi") != NULL) { | |
| rwl_wifi_flag = 1; | |
| } else { | |
| rwl_wifi_flag = 0; | |
| } | |
| /* Allocate buffers */ | |
| if ((parmsVal = malloc(MAX_PARMS_BUFF))== NULL) { | |
| DPRINT_ERR(WFA_ERR, "malloc failed allocating parmsVal\n"); | |
| if((errno_defined = Stop_Socket_Service()) != 0){ | |
| DPRINT_ERR(WFA_ERR, "Stop_Socket_Service failed\n"); | |
| } | |
| return 0; | |
| } | |
| if ((respBuf = malloc(WFA_BUFF_512))== NULL) { | |
| DPRINT_ERR(WFA_ERR, "malloc failed allocating respBuf\n"); | |
| if((errno_defined = Stop_Socket_Service()) != 0){ | |
| DPRINT_ERR(WFA_ERR, "Stop_Socket_Service failed\n"); | |
| } | |
| free(parmsVal); | |
| return 0; | |
| } | |
| DPRINT_INFO(WFA_OUT, "rwl_client_path = %s\n", rwl_client_path); | |
| /* Create TCP socket for getting the commands from tc_cli */ | |
| if ((tmsockfd = wfaCreateTCPServSock(myport))== -1) { | |
| DPRINT_ERR(WFA_ERR, "Failed to open socket\n"); | |
| if((errno_defined = Stop_Socket_Service()) != 0){ | |
| DPRINT_ERR(WFA_ERR, "Stop_Socket_Service failed\n"); | |
| } | |
| return 0; | |
| } | |
| maxfdn1 = tmsockfd + 1; | |
| FD_ZERO(&sockSet); | |
| for (;;) | |
| { | |
| FD_ZERO(&sockSet); | |
| FD_SET(tmsockfd, &sockSet); | |
| maxfdn1 = tmsockfd + 1; | |
| if (gCaSockfd != -1) { | |
| FD_SET(gCaSockfd, &sockSet); | |
| if (maxfdn1 < (int)gCaSockfd) | |
| maxfdn1 = gCaSockfd + 1; | |
| } | |
| /* | |
| * The timer will be set for transaction traffic if no echo is back | |
| * The timeout from the select call force to send a new packet | |
| */ | |
| nfds = 0; | |
| if ((nfds = select(maxfdn1, &sockSet, NULL, NULL, NULL)) < 0) { | |
| if (error_check(errno_defined)) | |
| continue; | |
| else | |
| DPRINT_WARNING(WFA_WNG, "select error %i", errno_defined); | |
| } | |
| DPRINT_INFO(WFA_OUT, "new event \n"); | |
| if (FD_ISSET(tmsockfd, &sockSet)) { | |
| gCaSockfd = wfaAcceptTCPConn(tmsockfd); | |
| DPRINT_INFO(WFA_OUT, "accept new connection\n"); | |
| FD_SET(gCaSockfd, &sockSet); | |
| } | |
| if (gCaSockfd > 0 && FD_ISSET(gCaSockfd, &sockSet)) { | |
| memset(xcCmdBuf, 0, WFA_BUFF_1K); | |
| memset(gRespStr, 0, WFA_BUFF_512); | |
| nbytes = wfaCtrlRecv(gCaSockfd, xcCmdBuf); | |
| if (nbytes <= 0) { | |
| asd_shutDown(gCaSockfd); | |
| asd_closeSocket(gCaSockfd); | |
| gCaSockfd = -1; | |
| continue; | |
| } | |
| memset(respStr, 0, WFA_BUFF_128); | |
| sprintf(respStr, "status,RUNNING\r\n"); | |
| wfaCtrlSend(gCaSockfd, (BYTE *)respStr, strlen(respStr)); | |
| /* WFA Comment :having this is for slowing down unexpected | |
| * output result on CLI command sometimes | |
| */ | |
| asd_sleep(1); | |
| DPRINT_INFO(WFA_OUT, "%s\n", respStr); | |
| DPRINT_INFO(WFA_OUT, "message %s %i\n", xcCmdBuf, nbytes); | |
| slen = (int )strlen((char *)xcCmdBuf); | |
| strncpy(command, (char*)xcCmdBuf, strlen((char*)xcCmdBuf)); | |
| /* The carriage return and newline character need to be | |
| * removed before sending the command to the DUT for the TCL | |
| * scripts to run correctly. | |
| */ | |
| strtok(command, "\r\n"); | |
| DPRINT_INFO(WFA_OUT, "last %x last-1 %x last-2 %x last-3 %x\n", cmdName[slen], cmdName[slen-1], cmdName[slen-2], cmdName[slen-3]); | |
| xcCmdBuf[slen-3] = '\0'; | |
| isFound = 0; | |
| DutCmd = 0; | |
| /* tokenize for the command name. Rest of the command buffer | |
| * is copied to pcmdStr for command processing later. | |
| */ | |
| memcpy(cmdName, strtok_r((char *)xcCmdBuf, ",", (char **)&pcmdStr), 32); | |
| i = 0; | |
| /* Check if we need to execute the command using rwl client */ | |
| while (nameStr[i].type != -1) { | |
| if ((strcmp(nameStr[i].name, cmdName) == 0)) { | |
| DutCmd = 1; /* Execute the command on the server e.g tg commands */ | |
| break; | |
| } | |
| i++; | |
| } | |
| /* Search for the command to be executed using rwl client */ | |
| if (!DutCmd) { | |
| i = 0; | |
| while (nameLocalStr[i].type != -1) { | |
| if ((strcmp(nameLocalStr[i].name, cmdName) == 0)) { | |
| /* Found a command to be executed using rwl client */ | |
| isFound = 1; | |
| break; | |
| } | |
| i++; | |
| } | |
| } /* !DutCmd */ | |
| DPRINT_INFO(WFA_OUT, "cmdName is %s\n", cmdName); | |
| memset(pcmdBuf, 0, WFA_BUFF_1K); | |
| /* Check for the valid command and the valid arguements for the command | |
| * and return STATUS INVLID for commands that do not exist or if the arguements | |
| * for the command are invalid. | |
| */ | |
| if ((!isFound && !DutCmd) | |
| || (DutCmd && (nameStr[i].cmdProcFunc(pcmdStr, pcmdBuf, &cmdLen)==FALSE)) | |
| || (!DutCmd && (nameLocalStr[i].cmdProcFunc(pcmdStr, pcmdBuf, &cmdLen)==FALSE))) { | |
| asd_sleep(1); | |
| sprintf(respStr, "status,INVALID\r\n"); | |
| wfaCtrlSend(gCaSockfd, (BYTE *)respStr, WFA_BUFF_128);/* Buffer size modified from strlen(respStr) on 21/11/07 */ | |
| DPRINT_WARNING(WFA_WNG, "Incorrect command syntax\n"); | |
| continue; | |
| } | |
| /* | |
| * Decode the command that is parsed above to find the actual function pointer | |
| * that needs to be executed. (decode for xcCmdTag ) | |
| * Commands that use rwl client are processed here. | |
| */ | |
| if (!DutCmd && isFound) { | |
| /* reset two commond storages used by control functions */ | |
| wfaDecodeTLV(pcmdBuf, cmdLen, &xcCmdTag, &cmdLen, parmsVal); | |
| memset(respBuf, 0, WFA_BUFF_512); | |
| respLen = 0; | |
| /* reset two commond storages used by control functions */ | |
| memset(gCmdStr, 0, WFA_CMD_STR_SZ); | |
| /* command process function defined in wfa_cs.c or wfa_tg.c */ | |
| gWfaCmdFuncTbl[xcCmdTag](cmdLen, parmsVal, &respLen, (BYTE *)respBuf); | |
| tag = ((wfaTLV *)respBuf)->tag; | |
| DPRINT_INFO(WFA_OUT, "bytes=%i,%i,%x %x %x %x \n", ((wfaTLV *)respBuf)->tag,((wfaTLV *)respBuf)->len, *(respBuf+4), *(respBuf+5), *(respBuf+6), *(respBuf+7)); | |
| DPRINT_INFO(WFA_OUT, "tag %i \n", tag-WFA_STA_COMMANDS_END); | |
| /* Response for the executed command is updated using the below function pointer | |
| * table | |
| */ | |
| if ((tag != 0 && tag < WFA_STA_RESPONSE_END) && | |
| wfaCmdRespProcFuncTbl[tag-WFA_STA_COMMANDS_END] != NULL) { | |
| wfaCmdRespProcFuncTbl[tag-WFA_STA_COMMANDS_END](respBuf); | |
| } else { | |
| DPRINT_WARNING(WFA_WNG, "function not defined\n"); | |
| memset(respBuf, 0, sizeof (respBuf)); | |
| memset(pcmdBuf, 0, sizeof (pcmdBuf)); | |
| } | |
| } else { | |
| /* Commands that need to be executed at DUT are processed here | |
| * TG commands for example | |
| */ | |
| /*In case of Multiple streams the commands will have space after each | |
| * streamid. So Look for \n for the end of command. | |
| */ | |
| strtok(command, "\n"); | |
| trafficPath = malloc(WFA_BUFF_1K); | |
| strcpy(trafficPath, rwl_client_path); | |
| /* e.g wl --socket <IP Addr> <Port no> asd ca_get_version */ | |
| strncat(trafficPath, " asd ", 5); | |
| strncat(trafficPath, command, strlen(command)); | |
| strncat(trafficPath, " > ", 3); | |
| if ((fp = asd_cmd_exec(trafficPath)) == NULL) | |
| continue; | |
| memset(trafficPath, 0, WFA_BUFF_1K); | |
| if (fread(trafficPath, sizeof(char), RESPONSE_SIZE, fp) <= 0) | |
| strcpy(trafficPath, "status,ERROR\r\n"); | |
| DPRINT_INFO(WFA_OUT, "%s %d\n", trafficPath, strlen(trafficPath)); | |
| wfaCtrlSend(gCaSockfd, (BYTE *)trafficPath, strlen(trafficPath)); | |
| file_cleanup(fp); | |
| memset(command, 0, strlen(command)); | |
| free(trafficPath); | |
| } /* DutCmd */ | |
| } /* done with if(gCaSockfd) */ | |
| } /* for */ | |
| if((errno_defined = Stop_Socket_Service()) != 0){ | |
| DPRINT_ERR(WFA_ERR, "Stop_Socket_Service failed\n"); | |
| } | |
| asd_closeSocket(gCaSockfd); | |
| return 0; | |
| } |