geom_gate userland utility improvements
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

294 lines
7.5 KiB

  1. /*
  2. * Sample showing how to do SCP transfers in a non-blocking manner.
  3. *
  4. * The sample code has default values for host name, user name, password
  5. * and path to copy, but you can specify them on the command line like:
  6. *
  7. * "scp_nonblock 192.168.0.1 user password /tmp/secrets"
  8. */
  9. #include "libssh2_config.h"
  10. #include <libssh2.h>
  11. #ifdef HAVE_WINSOCK2_H
  12. # include <winsock2.h>
  13. #endif
  14. #ifdef HAVE_SYS_SOCKET_H
  15. # include <sys/socket.h>
  16. #endif
  17. #ifdef HAVE_NETINET_IN_H
  18. # include <netinet/in.h>
  19. #endif
  20. #ifdef HAVE_SYS_SELECT_H
  21. # include <sys/select.h>
  22. #endif
  23. # ifdef HAVE_UNISTD_H
  24. #include <unistd.h>
  25. #endif
  26. #ifdef HAVE_ARPA_INET_H
  27. # include <arpa/inet.h>
  28. #endif
  29. #ifdef HAVE_SYS_TIME_H
  30. # include <sys/time.h>
  31. #endif
  32. #include <sys/types.h>
  33. #include <fcntl.h>
  34. #include <errno.h>
  35. #include <stdio.h>
  36. #include <ctype.h>
  37. #ifdef HAVE_GETTIMEOFDAY
  38. /* diff in ms */
  39. static long tvdiff(struct timeval newer, struct timeval older)
  40. {
  41. return (newer.tv_sec-older.tv_sec)*1000+
  42. (newer.tv_usec-older.tv_usec)/1000;
  43. }
  44. #endif
  45. static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
  46. {
  47. struct timeval timeout;
  48. int rc;
  49. fd_set fd;
  50. fd_set *writefd = NULL;
  51. fd_set *readfd = NULL;
  52. int dir;
  53. timeout.tv_sec = 10;
  54. timeout.tv_usec = 0;
  55. FD_ZERO(&fd);
  56. FD_SET(socket_fd, &fd);
  57. /* now make sure we wait in the correct direction */
  58. dir = libssh2_session_block_directions(session);
  59. if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
  60. readfd = &fd;
  61. if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
  62. writefd = &fd;
  63. rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
  64. return rc;
  65. }
  66. int main(int argc, char *argv[])
  67. {
  68. unsigned long hostaddr;
  69. int sock, i, auth_pw = 1;
  70. struct sockaddr_in sin;
  71. const char *fingerprint;
  72. LIBSSH2_SESSION *session;
  73. LIBSSH2_CHANNEL *channel;
  74. const char *username = "username";
  75. const char *password = "password";
  76. const char *scppath = "/tmp/TEST";
  77. libssh2_struct_stat fileinfo;
  78. #ifdef HAVE_GETTIMEOFDAY
  79. struct timeval start;
  80. struct timeval end;
  81. long time_ms;
  82. #endif
  83. int rc;
  84. int spin = 0;
  85. libssh2_struct_stat_size got = 0;
  86. libssh2_struct_stat_size total = 0;
  87. #ifdef WIN32
  88. WSADATA wsadata;
  89. int err;
  90. err = WSAStartup(MAKEWORD(2, 0), &wsadata);
  91. if(err != 0) {
  92. fprintf(stderr, "WSAStartup failed with error: %d\n", err);
  93. return 1;
  94. }
  95. #endif
  96. if(argc > 1) {
  97. hostaddr = inet_addr(argv[1]);
  98. }
  99. else {
  100. hostaddr = htonl(0x7F000001);
  101. }
  102. if(argc > 2) {
  103. username = argv[2];
  104. }
  105. if(argc > 3) {
  106. password = argv[3];
  107. }
  108. if(argc > 4) {
  109. scppath = argv[4];
  110. }
  111. rc = libssh2_init(0);
  112. if(rc != 0) {
  113. fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
  114. return 1;
  115. }
  116. /* Ultra basic "connect to port 22 on localhost"
  117. * Your code is responsible for creating the socket establishing the
  118. * connection
  119. */
  120. sock = socket(AF_INET, SOCK_STREAM, 0);
  121. sin.sin_family = AF_INET;
  122. sin.sin_port = htons(22);
  123. sin.sin_addr.s_addr = hostaddr;
  124. if(connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in))) {
  125. fprintf(stderr, "failed to connect!\n");
  126. return -1;
  127. }
  128. /* Create a session instance */
  129. session = libssh2_session_init();
  130. if(!session)
  131. return -1;
  132. /* Since we have set non-blocking, tell libssh2 we are non-blocking */
  133. libssh2_session_set_blocking(session, 0);
  134. #ifdef HAVE_GETTIMEOFDAY
  135. gettimeofday(&start, NULL);
  136. #endif
  137. /* ... start it up. This will trade welcome banners, exchange keys,
  138. * and setup crypto, compression, and MAC layers
  139. */
  140. while((rc = libssh2_session_handshake(session, sock)) ==
  141. LIBSSH2_ERROR_EAGAIN);
  142. if(rc) {
  143. fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
  144. return -1;
  145. }
  146. /* At this point we havn't yet authenticated. The first thing to do
  147. * is check the hostkey's fingerprint against our known hosts Your app
  148. * may have it hard coded, may go to a file, may present it to the
  149. * user, that's your call
  150. */
  151. fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
  152. fprintf(stderr, "Fingerprint: ");
  153. for(i = 0; i < 20; i++) {
  154. fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
  155. }
  156. fprintf(stderr, "\n");
  157. if(auth_pw) {
  158. /* We could authenticate via password */
  159. while((rc = libssh2_userauth_password(session, username, password)) ==
  160. LIBSSH2_ERROR_EAGAIN);
  161. if(rc) {
  162. fprintf(stderr, "Authentication by password failed.\n");
  163. goto shutdown;
  164. }
  165. }
  166. else {
  167. /* Or by public key */
  168. while((rc = libssh2_userauth_publickey_fromfile(session, username,
  169. "/home/username/"
  170. ".ssh/id_rsa.pub",
  171. "/home/username/"
  172. ".ssh/id_rsa",
  173. password)) ==
  174. LIBSSH2_ERROR_EAGAIN);
  175. if(rc) {
  176. fprintf(stderr, "\tAuthentication by public key failed\n");
  177. goto shutdown;
  178. }
  179. }
  180. #if 0
  181. libssh2_trace(session, LIBSSH2_TRACE_CONN);
  182. #endif
  183. /* Request a file via SCP */
  184. fprintf(stderr, "libssh2_scp_recv2()!\n");
  185. do {
  186. channel = libssh2_scp_recv2(session, scppath, &fileinfo);
  187. if(!channel) {
  188. if(libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) {
  189. char *err_msg;
  190. libssh2_session_last_error(session, &err_msg, NULL, 0);
  191. fprintf(stderr, "%s\n", err_msg);
  192. goto shutdown;
  193. }
  194. else {
  195. fprintf(stderr, "libssh2_scp_recv() spin\n");
  196. waitsocket(sock, session);
  197. }
  198. }
  199. } while(!channel);
  200. fprintf(stderr, "libssh2_scp_recv() is done, now receive data!\n");
  201. while(got < fileinfo.st_size) {
  202. char mem[1024*24];
  203. int rc;
  204. do {
  205. int amount = sizeof(mem);
  206. if((fileinfo.st_size -got) < amount) {
  207. amount = (int)(fileinfo.st_size - got);
  208. }
  209. /* loop until we block */
  210. rc = libssh2_channel_read(channel, mem, amount);
  211. if(rc > 0) {
  212. write(1, mem, rc);
  213. got += rc;
  214. total += rc;
  215. }
  216. } while(rc > 0);
  217. if((rc == LIBSSH2_ERROR_EAGAIN) && (got < fileinfo.st_size)) {
  218. /* this is due to blocking that would occur otherwise
  219. so we loop on this condition */
  220. spin++;
  221. waitsocket(sock, session); /* now we wait */
  222. continue;
  223. }
  224. break;
  225. }
  226. #ifdef HAVE_GETTIMEOFDAY
  227. gettimeofday(&end, NULL);
  228. time_ms = tvdiff(end, start);
  229. fprintf(stderr, "Got %ld bytes in %ld ms = %.1f bytes/sec spin: %d\n",
  230. (long)total,
  231. time_ms, total/(time_ms/1000.0), spin);
  232. #else
  233. fprintf(stderr, "Got %ld bytes spin: %d\n", (long)total, spin);
  234. #endif
  235. libssh2_channel_free(channel);
  236. channel = NULL;
  237. shutdown:
  238. libssh2_session_disconnect(session,
  239. "Normal Shutdown, Thank you for playing");
  240. libssh2_session_free(session);
  241. #ifdef WIN32
  242. closesocket(sock);
  243. #else
  244. close(sock);
  245. #endif
  246. fprintf(stderr, "all done\n");
  247. libssh2_exit();
  248. return 0;
  249. }