RDK Documentation (Open Sourced RDK Components)
fcgiproxy.c
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2016 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 
21 /**
22 * @defgroup trm
23 * @{
24 * @defgroup proxy
25 * @{
26 **/
27 
28 
29 #include <arpa/inet.h>
30 #include <sys/socket.h>
31 #include <sys/un.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <fcntl.h>
35 #include <errno.h>
36 #include <unistd.h>
37 #include "rdk_debug.h"
38 #include "safec_lib.h"
39 
40 enum MessageType {
41  REQUEST = 0x1234,
42  RESPONSE = 0x1800,
43  NOTIFICATION = 0x1400,
44  UNKNOWN,
45 };
46 
47 static int trm_socket_fd = -1;
48 
49 static int connect_to_trm(const char *ip, int port, int *trm_fd)
50 {
51  int socket_fd = -1;
52  int socket_error = 0;
53  struct sockaddr_in trm_address = {0}; /*Initialize the struct - Coverty DELIA-4581*/
54 
55 
56  trm_address.sin_family = AF_INET;
57  trm_address.sin_addr.s_addr = inet_addr(ip);
58  trm_address.sin_port = htons(port);
59 
60  socket_fd = socket(AF_INET, SOCK_STREAM, 0);
61  fprintf(stderr, "Connecting to remote\r\n");
62  while(1) {
63  static int retry_count = 10;
64  socket_error = connect(socket_fd, (struct sockaddr *) &trm_address, sizeof(struct sockaddr_in));
65  if (socket_error == ECONNREFUSED && retry_count > 0) {
66  fprintf(stderr, "TRM Server is not started...retry to connect\r\n");
67  sleep(2);
68  retry_count--;
69  }
70  else {
71  break;
72  }
73  }
74 
75  if (socket_error == 0){
76  fprintf(stderr, "Connected\r\n");
77 
78  int current_flags = fcntl(socket_fd, F_GETFL, 0);
79  current_flags &= (~O_NONBLOCK);
80  /* RDKSEC-811 coverity fix-CHECKED_RETURN */
81  if (fcntl(socket_fd, F_SETFL, current_flags) < 0) {
82  RDK_LOG(RDK_LOG_DEBUG, "LOG.RDK.TRM", "fcntl failed");
83  close(socket_fd);
84  *trm_fd = -1;
85  socket_error = -1;
86  return socket_error;
87  }
88  *trm_fd = socket_fd;
89  }
90  else {
91  close(socket_fd);
92  *trm_fd = -1;
93  }
94 
95  return socket_error;
96 }
97 
98 #include "fcgi_stdio.h"
99 
100 int main(int argc, char *argv[])
101 {
102  int opt,itr = 1;
103  char *debugConfigFile = NULL;
104 
105  printf("Starting TRM-FastCGI-Proxy\r\n");
106  /* First create a persistent connection to TRM */
107  int is_connected = 0;
108  errno_t safec_rc = -1;
109  int ind = -1;
110 
111  while (itr < argc)
112  {
113  safec_rc = strcmp_s("--debugconfig", strlen("--debugconfig"), argv[itr], &ind);
114  ERR_CHK(safec_rc);
115  if((safec_rc == EOK) && (ind == 0))
116  {
117  itr++;
118  if (itr < argc)
119  {
120  debugConfigFile = argv[itr];
121  }
122  else
123  {
124  break;
125  }
126  }
127  itr++;
128  }
129 
130  rdk_logger_init(debugConfigFile);
131 
132  RDK_LOG(RDK_LOG_DEBUG, "LOG.RDK.TRM", "This is a test line");
133 
134  is_connected = (connect_to_trm(argv[1], atoi(argv[2]), &trm_socket_fd) == 0);
135 
136  while (is_connected && FCGI_Accept() >= 0) {
137  /* Now start the fcgi loop */
138  char *content_length = getenv("CONTENT_LENGTH");
139  int payload_length = 0;
140  if (content_length != NULL) {
141  payload_length = strtol(content_length, NULL, 10);
142  fprintf(stderr, "content length is %d\r\n", payload_length);
143  }
144  else {
145  payload_length = 0;
146  }
147 
148  if (payload_length != 0) {
149  /* First prepend header */
150  static int message_id = 0x1000;
151  const int header_length = 16;
152  unsigned char *buf = (unsigned char *) malloc(payload_length + header_length);
153  int idx = 0;
154  /* Magic Word */
155  buf[idx++] = 'T';
156  buf[idx++] = 'R';
157  buf[idx++] = 'M';
158  buf[idx++] = 'S';
159  /* Type, set to UNKNOWN, as it is not used right now*/
160  buf[idx++] = (UNKNOWN & 0xFF000000) >> 24;
161  buf[idx++] = (UNKNOWN & 0x00FF0000) >> 16;
162  buf[idx++] = (UNKNOWN & 0x0000FF00) >> 8;
163  buf[idx++] = (UNKNOWN & 0x000000FF) >> 0;
164  /* Message id */
165  ++message_id;
166  buf[idx++] = (message_id & 0xFF000000) >> 24;
167  buf[idx++] = (message_id & 0x00FF0000) >> 16;
168  buf[idx++] = (message_id & 0x0000FF00) >> 8;
169  buf[idx++] = (message_id & 0x000000FF) >> 0;
170  /* Payload length */
171  buf[idx++] = (payload_length & 0xFF000000) >> 24;
172  buf[idx++] = (payload_length & 0x00FF0000) >> 16;
173  buf[idx++] = (payload_length & 0x0000FF00) >> 8;
174  buf[idx++] = (payload_length & 0x000000FF) >> 0;
175  /* Read payload from fastcgi */
176  int read_fcgi_count = fread((void *)&buf[idx], 1, payload_length, stdin);
177  if (read_fcgi_count == 0) {
178  free(buf);
179  continue;
180  }
181 
182  fprintf(stderr, "At %d Read from FastCGI %d vs expected %d\r\n", idx, read_fcgi_count, payload_length);
183  fprintf(stderr, "\r\n========REQUEST MSG================================================\r\n[");
184  for (idx = 0; idx < (header_length); idx++) {
185  fprintf(stderr, "%02x", buf[idx]);
186  }
187  for (; idx < (payload_length + header_length); idx++) {
188  fprintf(stderr, "%c", buf[idx]);
189  }
190 
191  fprintf(stderr, "]At %d\r\n==============================================================\r\n", idx);
192 
193  /* Write payload from fastcgi to TRM */
194  int write_trm_count = write(trm_socket_fd, buf, payload_length + header_length);
195  fprintf(stderr, "Send to TRM %d vs expected %d\r\n", write_trm_count, payload_length + header_length);
196  free(buf);
197 
198  if (write_trm_count != 0) {
199  buf = (char *) malloc(header_length);
200  /* Read Response from TRM, read header first, then payload */
201  int read_trm_count = read(trm_socket_fd, buf, header_length);
202  fprintf(stderr, "Read Header from TRM %d vs expected %d\r\n", read_trm_count, header_length);
203  fprintf(stderr, "\r\n=====RESPONSE HEADER===================================================\r\n[");
204 
205  for (idx = 0; idx < (header_length); idx++) {
206  fprintf(stderr, "%02x", buf[idx]);
207  }
208  fprintf(stderr, "\r\n==============================================================\r\n[");
209 
210  if (read_trm_count == header_length) {
211  int payload_length_offset = 12;
212  payload_length =((((unsigned char)(buf[payload_length_offset+0])) << 24) |
213  (((unsigned char)(buf[payload_length_offset+1])) << 16) |
214  (((unsigned char)(buf[payload_length_offset+2])) << 8 ) |
215  (((unsigned char)(buf[payload_length_offset+3])) << 0 ));
216 
217  free(buf);
218  fprintf(stderr, " TRM Response payloads is %d and header %d\r\n", payload_length, header_length);
219  fflush(stderr);
220 
221  buf = (char *) malloc(payload_length);
222  read_trm_count = read(trm_socket_fd, buf, payload_length);
223  fprintf(stderr, "Read Payload from TRM %d vs expected %d\r\n", read_trm_count, payload_length);
224 
225  if (read_trm_count != 0) {
226  /* Write Response from TRM to fastcgi */
227  printf("Content-type: text/html\r\n"
228  "Content-length:%d\r\n"
229  "Content-type:application/json\r\n"
230  "\r\n",
231  payload_length);
232 
233  int write_fcgi_count = fwrite((void *)buf, 1, payload_length, stdout);
234  fprintf(stderr, "Send to FastCGI %d vs expected %d\r\n", write_fcgi_count, payload_length);
235  if (write_fcgi_count == 0) {
236  free(buf);
237  continue;
238  }
239  }
240  else {
241  /* retry connect after payload-read failure*/
242  is_connected = 0;
243  }
244  free(buf);
245  }
246  else {
247  free(buf);
248  /* retry connect after header-read failure */
249  is_connected = 0;
250  }
251  }
252  else {
253  /* retry connect after write failure*/
254  is_connected = 0;
255  }
256  }
257 
258  if (!is_connected) {
259  printf("Content-type: text/html\r\n"
260  "Content-length:%d\r\n"
261  "Content-type:application/json\r\n"
262  "\r\n",
263  payload_length);
264 
265  FCGI_Finish();
266  is_connected = (connect_to_trm(argv[1], atoi(argv[2]), &trm_socket_fd) == 0);
267  }
268  }
269 
270  fprintf(stderr, "Out of FCGI Loop\r\n");
271 }
272 
273 
274 /** @} */
275 /** @} */
rdk_debug.h
RDK_LOG
#define RDK_LOG
Definition: rdk_debug.h:258
rdk_logger_init
rdk_Error rdk_logger_init(const char *debugConfigFile)
Initialize the logger. Sets up the environment variable storage by parsing debug configuration file t...
Definition: rdk_logger_init.c:57