/ api-example.c
api-example.c
1 /* 2 * Copyright 2011 Kano 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License as published by the Free 6 * Software Foundation; either version 3 of the License, or (at your option) 7 * any later version. See COPYING for more details. 8 */ 9 10 /* Compile: 11 * gcc api-example.c -Icompat/jansson-2.9/src -o cgminer-api 12 */ 13 14 #include "config.h" 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <ctype.h> 20 #include <unistd.h> 21 #include <stdbool.h> 22 #include <stdint.h> 23 #include <sys/types.h> 24 25 #include "compat.h" 26 #include "util.h" 27 28 #if defined(unix) || defined(__APPLE__) 29 #include <errno.h> 30 #include <sys/socket.h> 31 #include <netinet/in.h> 32 #include <arpa/inet.h> 33 #include <netdb.h> 34 35 #define SOCKETFAIL(a) ((a) < 0) 36 #define INVSOCK -1 37 #define CLOSESOCKET close 38 39 #define SOCKETINIT {} 40 41 #define SOCKERRMSG strerror(errno) 42 #endif 43 44 #ifdef WIN32 45 #include <winsock2.h> 46 47 #define SOCKETTYPE SOCKET 48 #define SOCKETFAIL(a) ((a) == SOCKET_ERROR) 49 #define INVSOCK INVALID_SOCKET 50 #define CLOSESOCKET closesocket 51 52 static char WSAbuf[1024]; 53 54 struct WSAERRORS { 55 int id; 56 char *code; 57 } WSAErrors[] = { 58 { 0, "No error" }, 59 { WSAEINTR, "Interrupted system call" }, 60 { WSAEBADF, "Bad file number" }, 61 { WSAEACCES, "Permission denied" }, 62 { WSAEFAULT, "Bad address" }, 63 { WSAEINVAL, "Invalid argument" }, 64 { WSAEMFILE, "Too many open sockets" }, 65 { WSAEWOULDBLOCK, "Operation would block" }, 66 { WSAEINPROGRESS, "Operation now in progress" }, 67 { WSAEALREADY, "Operation already in progress" }, 68 { WSAENOTSOCK, "Socket operation on non-socket" }, 69 { WSAEDESTADDRREQ, "Destination address required" }, 70 { WSAEMSGSIZE, "Message too long" }, 71 { WSAEPROTOTYPE, "Protocol wrong type for socket" }, 72 { WSAENOPROTOOPT, "Bad protocol option" }, 73 { WSAEPROTONOSUPPORT, "Protocol not supported" }, 74 { WSAESOCKTNOSUPPORT, "Socket type not supported" }, 75 { WSAEOPNOTSUPP, "Operation not supported on socket" }, 76 { WSAEPFNOSUPPORT, "Protocol family not supported" }, 77 { WSAEAFNOSUPPORT, "Address family not supported" }, 78 { WSAEADDRINUSE, "Address already in use" }, 79 { WSAEADDRNOTAVAIL, "Can't assign requested address" }, 80 { WSAENETDOWN, "Network is down" }, 81 { WSAENETUNREACH, "Network is unreachable" }, 82 { WSAENETRESET, "Net connection reset" }, 83 { WSAECONNABORTED, "Software caused connection abort" }, 84 { WSAECONNRESET, "Connection reset by peer" }, 85 { WSAENOBUFS, "No buffer space available" }, 86 { WSAEISCONN, "Socket is already connected" }, 87 { WSAENOTCONN, "Socket is not connected" }, 88 { WSAESHUTDOWN, "Can't send after socket shutdown" }, 89 { WSAETOOMANYREFS, "Too many references, can't splice" }, 90 { WSAETIMEDOUT, "Connection timed out" }, 91 { WSAECONNREFUSED, "Connection refused" }, 92 { WSAELOOP, "Too many levels of symbolic links" }, 93 { WSAENAMETOOLONG, "File name too long" }, 94 { WSAEHOSTDOWN, "Host is down" }, 95 { WSAEHOSTUNREACH, "No route to host" }, 96 { WSAENOTEMPTY, "Directory not empty" }, 97 { WSAEPROCLIM, "Too many processes" }, 98 { WSAEUSERS, "Too many users" }, 99 { WSAEDQUOT, "Disc quota exceeded" }, 100 { WSAESTALE, "Stale NFS file handle" }, 101 { WSAEREMOTE, "Too many levels of remote in path" }, 102 { WSASYSNOTREADY, "Network system is unavailable" }, 103 { WSAVERNOTSUPPORTED, "Winsock version out of range" }, 104 { WSANOTINITIALISED, "WSAStartup not yet called" }, 105 { WSAEDISCON, "Graceful shutdown in progress" }, 106 { WSAHOST_NOT_FOUND, "Host not found" }, 107 { WSANO_DATA, "No host data of that type was found" }, 108 { -1, "Unknown error code" } 109 }; 110 111 static char *WSAErrorMsg() 112 { 113 char *msg; 114 int i; 115 int id = WSAGetLastError(); 116 117 /* Assume none of them are actually -1 */ 118 for (i = 0; WSAErrors[i].id != -1; i++) 119 if (WSAErrors[i].id == id) 120 break; 121 122 sprintf(WSAbuf, "Socket Error: (%d) %s", id, WSAErrors[i].code); 123 124 return &(WSAbuf[0]); 125 } 126 127 #define SOCKERRMSG WSAErrorMsg() 128 129 static WSADATA WSA_Data; 130 131 #define SOCKETINIT int wsa; \ 132 if (wsa = WSAStartup(0x0202, &WSA_Data)) { \ 133 printf("Socket startup failed: %d\n", wsa); \ 134 return 1; \ 135 } 136 137 #ifndef SHUT_RDWR 138 #define SHUT_RDWR SD_BOTH 139 #endif 140 #endif 141 142 static const char SEPARATOR = '|'; 143 static const char COMMA = ','; 144 static const char EQ = '='; 145 static int ONLY; 146 147 void display(char *buf) 148 { 149 char *nextobj, *item, *nextitem, *eq; 150 int itemcount; 151 152 while (buf != NULL) { 153 nextobj = strchr(buf, SEPARATOR); 154 if (nextobj != NULL) 155 *(nextobj++) = '\0'; 156 157 if (*buf) { 158 item = buf; 159 itemcount = 0; 160 while (item != NULL) { 161 nextitem = strchr(item, COMMA); 162 if (nextitem != NULL) 163 *(nextitem++) = '\0'; 164 165 if (*item) { 166 eq = strchr(item, EQ); 167 if (eq != NULL) 168 *(eq++) = '\0'; 169 170 if (itemcount == 0) 171 printf("[%s%s] =>\n(\n", item, (eq != NULL && isdigit(*eq)) ? eq : ""); 172 173 if (eq != NULL) 174 printf(" [%s] => %s\n", item, eq); 175 else 176 printf(" [%d] => %s\n", itemcount, item); 177 } 178 179 item = nextitem; 180 itemcount++; 181 } 182 if (itemcount > 0) 183 puts(")"); 184 } 185 186 buf = nextobj; 187 } 188 } 189 190 #define SOCKSIZ 65535 191 192 int callapi(char *command, char *host, short int port) 193 { 194 struct hostent *ip; 195 struct sockaddr_in serv; 196 SOCKETTYPE sock; 197 int ret = 0; 198 int n; 199 char *buf = NULL; 200 size_t len, p; 201 202 SOCKETINIT; 203 204 ip = gethostbyname(host); 205 if (!ip) { 206 printf("Couldn't get hostname: '%s'\n", host); 207 return 1; 208 } 209 210 sock = socket(AF_INET, SOCK_STREAM, 0); 211 if (sock == INVSOCK) { 212 printf("Socket initialisation failed: %s\n", SOCKERRMSG); 213 return 1; 214 } 215 216 memset(&serv, 0, sizeof(serv)); 217 serv.sin_family = AF_INET; 218 serv.sin_addr = *((struct in_addr *)ip->h_addr); 219 serv.sin_port = htons(port); 220 221 if (SOCKETFAIL(connect(sock, (struct sockaddr *)&serv, sizeof(struct sockaddr)))) { 222 printf("Socket connect failed: %s\n", SOCKERRMSG); 223 return 1; 224 } 225 226 n = send(sock, command, strlen(command), 0); 227 if (SOCKETFAIL(n)) { 228 printf("Send failed: %s\n", SOCKERRMSG); 229 ret = 1; 230 } 231 else { 232 len = SOCKSIZ; 233 buf = malloc(len+1); 234 if (!buf) { 235 printf("Err: OOM (%d)\n", (int)(len+1)); 236 return 1; 237 } 238 p = 0; 239 while (42) { 240 if ((len - p) < 1) { 241 len += SOCKSIZ; 242 buf = realloc(buf, len+1); 243 if (!buf) { 244 printf("Err: OOM (%d)\n", (int)(len+1)); 245 return 1; 246 } 247 } 248 249 n = recv(sock, &buf[p], len - p , 0); 250 251 if (SOCKETFAIL(n)) { 252 printf("Recv failed: %s\n", SOCKERRMSG); 253 ret = 1; 254 break; 255 } 256 257 if (n == 0) 258 break; 259 260 p += n; 261 } 262 buf[p] = '\0'; 263 264 if (ONLY) 265 printf("%s\n", buf); 266 else { 267 printf("Reply was '%s'\n", buf); 268 display(buf); 269 } 270 } 271 272 CLOSESOCKET(sock); 273 274 return ret; 275 } 276 277 static char *trim(char *str) 278 { 279 char *ptr; 280 281 while (isspace(*str)) 282 str++; 283 284 ptr = strchr(str, '\0'); 285 while (ptr-- > str) { 286 if (isspace(*ptr)) 287 *ptr = '\0'; 288 } 289 290 return str; 291 } 292 293 int main(int argc, char *argv[]) 294 { 295 char *command = "summary"; 296 char *host = "127.0.0.1"; 297 short int port = 4028; 298 char *ptr; 299 int i = 1; 300 301 if (argc > 1) 302 if (strcmp(argv[1], "-?") == 0 303 || strcmp(argv[1], "-h") == 0 304 || strcmp(argv[1], "--help") == 0) { 305 fprintf(stderr, "usAge: %s [command [ip/host [port]]]\n", argv[0]); 306 return 1; 307 } 308 309 if (argc > 1) 310 if (strcmp(argv[1], "-o") == 0) { 311 ONLY = 1; 312 i = 2; 313 } 314 315 if (argc > i) { 316 ptr = trim(argv[i++]); 317 if (strlen(ptr) > 0) 318 command = ptr; 319 } 320 321 if (argc > i) { 322 ptr = trim(argv[i++]); 323 if (strlen(ptr) > 0) 324 host = ptr; 325 } 326 327 if (argc > i) { 328 ptr = trim(argv[i]); 329 if (strlen(ptr) > 0) 330 port = atoi(ptr); 331 } 332 333 return callapi(command, host, port); 334 }