1 /** @file
2   Windows version of the OOB Transmit application
3 
4   Copyright (c) 2011-2012, Intel Corporation
5   All rights reserved. This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include <OobTx.h>
16 
17 UINT8 mBuffer[8192];
18 UINT8 mOob[512];
19 
20 /**
21   Transmit out-of-band messages to the remote system.
22 
23   @param [in] ArgC        Argument count
24   @param [in] ArgV        Argument value array
25 
26   @retval 0               Successfully operation
27  **/
28 
29 int
OobTx(IN int ArgC,IN char ** ArgV)30 OobTx (
31   IN int ArgC,
32   IN char **ArgV
33   )
34 {
35   UINT32 BytesSent;
36   ssize_t BytesTransmitted;
37   UINT32 Index;
38   struct sockaddr_in LocalPort;
39   UINT32 OobInLine;
40   UINT16 PortNumber;
41   UINT32 RemoteAddress[4];
42   struct sockaddr_in RemotePort;
43   int RetVal;
44   UINT32 TransmittedAfter;
45   UINT32 TransmittedBefore;
46   UINT32 TransmittedOob;
47   SOCKET s;
48 
49   //
50   //  Create the socket
51   //
52   s = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
53   if ( -1 == s ) {
54     RetVal = GET_ERRNO;
55     printf ( "ERROR - socket error, errno: %d\r\n", RetVal );
56   }
57   else {
58     //
59     //  Use for/break; instead of goto
60     //
61     for ( ; ; ) {
62       //
63       //  Validate the arguments
64       //
65       if (( 2 > ArgC )
66         || ( 4 != sscanf ( ArgV[1],
67                            "%d.%d.%d.%d",
68                            &RemoteAddress[0],
69                            &RemoteAddress[1],
70                            &RemoteAddress[2],
71                            &RemoteAddress[3]))
72           || ( 224 < RemoteAddress[0])
73           || ( 255 < RemoteAddress[1])
74           || ( 255 < RemoteAddress[2])
75           || ( 255 < RemoteAddress[3])
76           || (( 0 == RemoteAddress[0])
77               && ( 0 == RemoteAddress[1])
78               && ( 0 == RemoteAddress[2])
79               && ( 0 == RemoteAddress[3]))) {
80         printf ( "%s  <remote IP address>  [optional: enables in-line OOB]\r\n", ArgV[0]);
81         RetVal = EINVAL;
82         break;
83       }
84 
85       //
86       //  Bind the socket to a local port
87       //
88       memset ( &LocalPort, 0, sizeof ( LocalPort ));
89       SIN_LEN ( LocalPort ) = sizeof ( LocalPort );
90       SIN_FAMILY ( LocalPort ) = AF_INET;
91       SIN_ADDR ( LocalPort ) = 0;
92       SIN_PORT ( LocalPort ) = 0;
93       RetVal = bind ( s,
94                       (struct sockaddr *)&LocalPort,
95                       sizeof ( LocalPort ));
96       if ( -1 == RetVal ) {
97         RetVal = GET_ERRNO;
98         printf ( "ERROR - bind error, errno: %d\r\n", RetVal );
99         break;
100       }
101 
102       //
103       //  Specify the remote port
104       //
105       PortNumber = OOB_RX_PORT;
106       memset ( &RemotePort, 0, sizeof ( RemotePort ));
107       SIN_LEN ( RemotePort ) = sizeof ( RemotePort );
108       SIN_FAMILY ( RemotePort ) = AF_INET;
109       SIN_ADDR ( RemotePort ) = ( RemoteAddress[3] << 24 )
110                               | ( RemoteAddress[2] << 16 )
111                               | ( RemoteAddress[1] << 8 )
112                               | RemoteAddress[0];
113       SIN_PORT ( RemotePort ) = htons ( PortNumber );
114 
115       //
116       //  Connect to the remote server
117       //
118       RetVal = connect ( s, (struct sockaddr *)&RemotePort, sizeof ( RemotePort ));
119       if ( -1 == RetVal ) {
120         RetVal = GET_ERRNO;
121         printf ( "ERROR - connect error, errno: %d\r\n", RetVal );
122         break;
123       }
124 
125       //
126       //  Select the OOB processing
127       //
128       OobInLine = ( 2 < ArgC );
129       RetVal = setsockopt ( s,
130                             SOL_SOCKET,
131                             SO_OOBINLINE,
132                             (char *)&OobInLine,
133                             sizeof ( OobInLine ));
134       if ( -1 == RetVal ) {
135         RetVal = GET_ERRNO;
136         printf ( "ERROR - setsockopt OOBINLINE error, errno: %d\r\n", RetVal );
137         break;
138       }
139       printf ( "%s\r\n", ( 0 != OobInLine ) ? "OOB messages are in-line"
140                                             : "OOB messages move to the head of the queue" );
141 
142       //
143       //  Initialize the messages
144       //
145       memset ( &mBuffer[0], 0, sizeof ( mBuffer ));
146       memset ( &mOob[0], 0x11, sizeof ( mOob ));
147 
148       //
149       //  Send the data before the out-of-band message
150       //
151       TransmittedBefore = 0;
152       for ( Index = 0; TX_MSGS_BEFORE > Index; Index++ ) {
153         BytesSent = 0;
154         do {
155           BytesTransmitted = send ( s,
156                                     &mBuffer[BytesSent],
157                                     sizeof ( mBuffer ) - BytesSent,
158                                     0 );
159           if ( -1 == BytesTransmitted ) {
160             RetVal = GET_ERRNO;
161             printf ( "ERROR - send before error, errno: %d\r\n", RetVal );
162             break;
163           }
164           BytesSent += (UINT32)BytesTransmitted;
165           RetVal = 0;
166         } while ( sizeof ( mBuffer ) > BytesSent );
167         if ( 0 != RetVal ) {
168           break;
169         }
170         TransmittedBefore += BytesSent;
171       }
172       if ( 0 != RetVal ) {
173         break;
174       }
175 
176       //
177       //  Send the out-of-band message
178       //
179       BytesSent = 0;
180       do {
181         BytesTransmitted = send ( s,
182                                   &mOob[BytesSent],
183                                   sizeof ( mOob ) - BytesSent,
184                                   MSG_OOB );
185         if ( -1 == BytesTransmitted ) {
186           RetVal = GET_ERRNO;
187           printf ( "ERROR - send OOB error, errno: %d\r\n", RetVal );
188           break;
189         }
190         BytesSent += (UINT32)BytesTransmitted;
191         RetVal = 0;
192       } while ( sizeof ( mOob ) > BytesSent );
193       if ( 0 != RetVal ) {
194         break;
195       }
196       TransmittedOob = BytesSent;
197 
198       //
199       //  Send the data after the out-of-band message
200       //
201       TransmittedAfter = 0;
202       for ( Index = 0; TX_MSGS_AFTER > Index; Index++ ) {
203         BytesSent = 0;
204         do {
205           BytesTransmitted = send ( s,
206                                     &mBuffer[BytesSent],
207                                     sizeof ( mBuffer ) - BytesSent,
208                                     0 );
209           if ( -1 == BytesTransmitted ) {
210             RetVal = GET_ERRNO;
211             printf ( "ERROR - send after error, errno: %d\r\n", RetVal );
212             break;
213           }
214           BytesSent += (UINT32)BytesTransmitted;
215           RetVal = 0;
216         } while ( sizeof ( mBuffer ) > BytesSent );
217         if ( 0 != RetVal ) {
218           break;
219         }
220         TransmittedAfter += BytesSent;
221       }
222 
223       //
224       //  Test completed successfully
225       //
226       if ( 0 == RetVal ) {
227         printf ( "Bytes before OOB:  %8d\r\n", TransmittedBefore );
228         printf ( "Out-of-band bytes: %8d\r\n", TransmittedOob );
229         printf ( "Bytes after OOB:   %8d\r\n", TransmittedAfter );
230         printf ( "                   --------\r\n" );
231         printf ( "Total Bytes:       %8d\r\n", TransmittedBefore
232                                                + TransmittedOob
233                                                + TransmittedAfter );
234       }
235       break;
236     }
237 
238     //
239     //  Close the socket
240     //
241     CLOSE_SOCKET ( s );
242   }
243 
244   //
245   //  Return the operation status
246   //
247   return RetVal;
248 }
249