diff --git a/hardsup/asynsrv_utility.c b/hardsup/asynsrv_utility.c index 93205646..b8bae76f 100644 --- a/hardsup/asynsrv_utility.c +++ b/hardsup/asynsrv_utility.c @@ -1833,4 +1833,209 @@ if (AsynSrv_errcode == 0) AsynSrv_call_depth--; return True; } +/* +**--------------------------------------------------------------------------- +** AsynSrv_Force: Open a connection to an RS-232-C Server. +** Thereby insisting on an own socket. +*/ + int AsynSrv_Force ( +/* ============ +*/ struct AsynSrv__info *asyn_info) { + + int i, status; + int my_skt; + char old_time_out[4]; + union { + char chars[4]; + int val; + } time_out; + char buff[128]; + struct RS__MsgStruct s_buff; + struct RS__RespStruct r_buff; + unsigned int oto_len, oto_status; + struct hostent *rmt_hostent; + struct in_addr *rmt_inet_addr_pntr; + struct in_addr rmt_inet_addr; + int rmt_sockname_len; + struct sockaddr_in lcl_sockname; + struct sockaddr_in rmt_sockname; + + char *errtxt_ptr; + int errcode, my_errno, my_vaxc_errno; +/*-------------------------------------------------------- +*/ + asyn_info->skt = 0; +/*-------------------------------------------------------- +** Initialise the error info stack and pre-set the +** routine name (in case of error). +*/ + AsynSrv_errcode = AsynSrv_errno = AsynSrv_vaxc_errno = 0; + strcpy (AsynSrv_routine[0], "AsynSrv_Open"); + AsynSrv_call_depth = 1; +/*-------------------------------------------------------- +** But, before going any further, do some quick checks on +** values in asyn_info. +*/ + if ((asyn_info->port <= 0) || + (asyn_info->port > 65535)) { + AsynSrv_errcode = ASYNSRV__BAD_PAR; /* Something is bad! */ + return False; + } + if (asyn_info->chan < 0) asyn_info->chan = 0; + if (asyn_info->chan > 255) asyn_info->chan = 0; +/*-------------------------------------------------------- +** Set up a new connection. +*/ + /*--------------------------- + ** Get the Internet address of the server. + */ + rmt_inet_addr.s_addr = inet_addr (asyn_info->host); + if (rmt_inet_addr.s_addr != -1) { + rmt_inet_addr_pntr = &rmt_inet_addr; + }else { + rmt_hostent = gethostbyname (asyn_info->host); + if (rmt_hostent == NULL) { + AsynSrv_errcode = ASYNSRV__BAD_HOST; + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); /* Save errno info */ + fprintf (stderr, "\nAsynSrv_Open/gethostbyname: Failed to get Internet " + "address of \"%s\".\n", asyn_info->host); + return False; + } + rmt_inet_addr_pntr = (struct in_addr *) rmt_hostent->h_addr_list[0]; + } + /*--------------------------- + ** Create a TCP/IP socket for connecting to server and bind it. + */ + my_skt = socket (AF_INET, SOCK_STREAM, 0); + if (my_skt <= 0) { + AsynSrv_errcode = ASYNSRV__BAD_SOCKET; + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); /* Save the errno info */ + fprintf (stderr, "\nAsynSrv_Open/socket: Failed to create a socket.\n"); + return False; + } + lcl_sockname.sin_family = AF_INET; + lcl_sockname.sin_port = htons (0); + lcl_sockname.sin_addr.s_addr = 0; + status = bind (my_skt, (struct sockaddr *) &lcl_sockname, + sizeof (lcl_sockname)); + if (status == -1) { + close (my_skt); + AsynSrv_errcode = ASYNSRV__BAD_BIND; + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); /* Save the errno info */ + fprintf (stderr, "\nAsynSrv_Open/bind: Failed to bind socket.\n"); + return False; + } + /*--------------------------- + ** Set short time-out (VMS systems only) + */ +#ifdef __VMS + oto_len = sizeof (old_time_out); /* Save current time-out first */ + oto_status = getsockopt (my_skt, IPPROTO_TCP, UCX$C_TCP_PROBE_IDLE, + old_time_out, &oto_len); + + if (oto_status == 0) { + time_out.val = AsynSrv_connect_tmo; /* Set new time-out */ + status = setsockopt (my_skt, IPPROTO_TCP, UCX$C_TCP_PROBE_IDLE, + time_out.chars, sizeof (time_out)); + } +#endif + /*--------------------------- + ** Connect to RS-232-C Server. + */ + rmt_sockname_len = sizeof (rmt_sockname); + rmt_sockname.sin_family = AF_INET; + rmt_sockname.sin_port = htons (asyn_info->port); + rmt_sockname.sin_addr.s_addr = rmt_inet_addr_pntr->s_addr; + status = connect (my_skt, (struct sockaddr *) &rmt_sockname, + sizeof (rmt_sockname)); + if (status != 0) { + close (my_skt); + AsynSrv_errcode = ASYNSRV__BAD_CONNECT; + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); /* Save the errno info */ + fprintf (stderr, + "\nAsynSrv_Open/connect: Failed to connect to server.\n"); + perror ("AsynSrv_Open"); + return False; + } + /*--------------------------- + ** Restore time-out (VMS only) + */ +#ifdef __VMS + if (oto_status == 0) { + setsockopt (my_skt, IPPROTO_TCP, UCX$C_TCP_PROBE_IDLE, + old_time_out, oto_len); + } +#endif + /*--------------------------------------------------- + ** Setup the defaults in the AsynSrv__info data structure. + */ + asyn_info->skt = my_skt; /* Return socket number to caller */ + + asyn_info->protocol_code = 0; /* Ensure protocol_code set to "unknown" */ + memcpy (asyn_info->protocol_id, "\0\0\0\0", + sizeof (asyn_info->protocol_id)); + asyn_info->cmnd_hdr_len = 4; + strcpy (asyn_info->cmnd_fmt, "%04d"); + asyn_info->rply_hdr_len = 4; + strcpy (asyn_info->rply_fmt, "%4d"); + + sprintf (buff, "%04d", asyn_info->chan); /* Convert channel # to ASCII */ + memcpy (asyn_info->chan_char, buff, sizeof (asyn_info->chan_char)); + + sprintf (buff, "%04d", AsynSrv_msec_tmo/100); /* Set dflt time-out .. + ** .. (deci-secs) */ + memcpy (asyn_info->tmo, buff, sizeof (asyn_info->tmo)); + + memcpy (asyn_info->eot, AsynSrv_eot, sizeof (asyn_info->eot)); /* Set .. + ** .. dflt terminator(s) */ + asyn_info->max_replies = 0; + asyn_info->n_replies = 0; + /* + ** Send a null command buffer to the server. This should give + ** a "protocol mismatch" error response and from this we can get + ** the actual protocol level supported by the server. + */ + status = AsynSrv_SendCmnds (asyn_info, &s_buff, &r_buff, NULL); + if (!status && (AsynSrv_errcode == ASYNSRV__BAD_PROT_LVL)) { + /* + ** As expected, we got a "protocol mismatch" error. + ** Save the server's protocol level for future use. + */ + memcpy (asyn_info->protocol_id, r_buff.s_pcol_lvl, + sizeof (r_buff.s_pcol_lvl)); + if (strncmp (r_buff.s_pcol_lvl, RS__PROTOCOL_ID_V01B, + strlen (RS__PROTOCOL_ID_V01B)) == 0) { + asyn_info->protocol_code = RS__PROTOCOL_CODE_V01B; + asyn_info->cmnd_hdr_len = 4; + strcpy (asyn_info->cmnd_fmt, "%04d"); + asyn_info->rply_hdr_len = 4; + strcpy (asyn_info->rply_fmt, "%4d"); + }else if (strncmp (r_buff.s_pcol_lvl, RS__PROTOCOL_ID, + strlen (RS__PROTOCOL_ID)) == 0) { + asyn_info->protocol_code = RS__PROTOCOL_CODE; + asyn_info->cmnd_hdr_len = 2; + strcpy (asyn_info->cmnd_fmt, "%02d"); + asyn_info->rply_hdr_len = 2; + strcpy (asyn_info->rply_fmt, "%2d"); + }else { + close (my_skt); + asyn_info->skt = 0; + fprintf (stderr, + "\nAsynSrv_Open: Server protocol level is unrecognised.\n" + " Server level is \"%4s\"\n", r_buff.s_pcol_lvl); + return False; + } + }else { + close (my_skt); + asyn_info->skt = 0; + AsynSrv_errcode = ASYNSRV__BAD_PROT_LVL; + fprintf (stderr, + "\nAsynSrv_Open: Problem getting protocol level of Server!\n"); + return False; + } + AsynSrv_errcode = AsynSrv_errno = AsynSrv_vaxc_errno = 0; + AsynSrv_call_depth = 0; + return True; + } + /*-------------------------------------------- End of AsynSrv_Utility.C -----*/