updartes.
[silc.git] / lib / silcclient / client_ftp.c
index 7f85a8db9e03b6176e6fe8f18c20bd6b3eec8e89..90642aa251d1f8fa4e9cf4ea34d59e72f3992368 100644 (file)
@@ -76,12 +76,12 @@ SILC_TASK_CALLBACK(silc_client_ftp_connected)
   if (opt != 0) {
     if (ctx->tries < 2) {
       /* Connection failed but lets try again */
-      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
-                      "Could not connect to client %s: %s",
-                      ctx->host, strerror(opt));
-      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
-                      "Connecting to port %d of client %s resumed", 
-                      ctx->port, ctx->host);
+      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+                                "Could not connect to client %s: %s",
+                                ctx->host, strerror(opt));
+      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
+                                "Connecting to port %d of client %s resumed", 
+                                ctx->port, ctx->host);
 
       /* Unregister old connection try */
       silc_schedule_unset_listen_fd(client->schedule, fd);
@@ -93,9 +93,9 @@ SILC_TASK_CALLBACK(silc_client_ftp_connected)
       ctx->tries++;
     } else {
       /* Connection failed and we won't try anymore */
-      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
-                      "Could not connect to client %s: %s",
-                      ctx->host, strerror(opt));
+      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+                                "Could not connect to client %s: %s",
+                                ctx->host, strerror(opt));
       silc_schedule_unset_listen_fd(client->schedule, fd);
       silc_net_close_connection(fd);
       silc_schedule_task_del(client->schedule, ctx->task);
@@ -312,10 +312,11 @@ static void silc_client_ftp_open_handle(SilcSFTP sftp,
                               O_RDWR | O_CREAT | O_EXCL);
   if (session->fd < 0) {
     /* Call monitor callback */
-    session->client->ops->say(session->client, session->conn, 
-                             SILC_CLIENT_MESSAGE_ERROR, 
-                             "File `%s' open failed: %s", session->filepath,
-                             strerror(errno));
+    session->client->internal->ops->say(session->client, session->conn, 
+                                       SILC_CLIENT_MESSAGE_ERROR, 
+                                       "File `%s' open failed: %s", 
+                                       session->filepath,
+                                       strerror(errno));
 
     if (session->monitor)
       (*session->monitor)(session->client, session->conn,
@@ -463,6 +464,14 @@ SILC_TASK_CALLBACK(silc_client_ftp_key_agreement_final)
 
   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
+    /* Call monitor callback */
+    if (session->monitor)
+      (*session->monitor)(session->client, session->conn,
+                         SILC_CLIENT_FILE_MONITOR_ERROR, 
+                         SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED, 0, 0,
+                         session->client_entry, session->session_id,
+                         session->filepath, session->monitor_context);
+
     /* Error occured during protocol */
     silc_ske_free_key_material(ctx->keymat);
     goto out;
@@ -762,38 +771,40 @@ void silc_client_ftp_session_free(SilcClientFtpSession session)
    indicated by the `client_entry'.  This will negotiate a secret key
    with the remote client before actually starting the transmission of
    the file.  The `monitor' callback will be called to monitor the
-   transmission of the file.
-
-   This returns a file session ID for the file transmission.  It can
-   be used to close the session (and abort the file transmission) by
-   calling the silc_client_file_close function.  The session ID is
-   also returned in the `monitor' callback. This returns 0 if the
-   file indicated by the `filepath' is being transmitted to the remote
-   client indicated by the `client_entry', already. */
-
-uint32 silc_client_file_send(SilcClient client,
-                            SilcClientConnection conn,
-                            SilcClientFileMonitor monitor,
-                            void *monitor_context,
-                            const char *local_ip,
-                            uint32 local_port,
-                            SilcClientEntry client_entry,
-                            const char *filepath)
+   transmission of the file. */
+
+SilcClientFileError 
+silc_client_file_send(SilcClient client,
+                     SilcClientConnection conn,
+                     SilcClientFileMonitor monitor,
+                     void *monitor_context,
+                     const char *local_ip,
+                     uint32 local_port,
+                     SilcClientEntry client_entry,
+                     const char *filepath,
+                     uint32 *session_id)
 {
   SilcClientFtpSession session;
   SilcBuffer keyagr, ftp;
   char *filename, *path;
+  int fd;
 
   SILC_LOG_DEBUG(("Start"));
 
   /* Check for existing session for `filepath'. */
   silc_dlist_start(conn->ftp_sessions);
   while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
-    if (!strcmp(session->filepath, filepath) && 
+    if (session->filepath && !strcmp(session->filepath, filepath) && 
        session->client_entry == client_entry)
-      return 0;
+      return SILC_CLIENT_FILE_ALREADY_STARTED;
   }
 
+  /* See whether the file exists, and can be opened in generally speaking */
+  fd = silc_file_open(filepath, O_RDONLY);
+  if (fd < 0)
+    return SILC_CLIENT_FILE_NO_SUCH_FILE;
+  silc_file_close(fd);
+
   /* Add new session */
   session = silc_calloc(1, sizeof(*session));
   session->session_id = ++conn->next_session_id;
@@ -835,6 +846,7 @@ uint32 silc_client_file_send(SilcClient client,
     SILC_LOG_DEBUG(("Could not create listener"));
     silc_free(session->hostname);
     session->hostname = NULL;
+    session->port = 0;
   } else {
     /* Listener ready */
     session->port = silc_net_get_local_port(session->listener);
@@ -860,7 +872,10 @@ uint32 silc_client_file_send(SilcClient client,
   silc_buffer_free(ftp);
   silc_free(path);
 
-  return session->session_id;
+  if (session_id)
+    *session_id = session->session_id;
+
+  return SILC_CLIENT_FILE_OK;
 }
 
 /* Receives a file from a client indicated by the `client_entry'.  The
@@ -918,9 +933,9 @@ silc_client_file_receive(SilcClient client,
     session->listener = silc_net_create_server(0, session->hostname);
     if (session->listener < 0) {
       SILC_LOG_DEBUG(("Could not create listener"));
-      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR, 
-                      "Cannot create listener on %s: %s", 
-                      session->hostname, strerror(errno));
+      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR, 
+                                "Cannot create listener on %s: %s", 
+                                session->hostname, strerror(errno));
       return SILC_CLIENT_FILE_ERROR;
     }
     session->port = silc_net_get_local_port(session->listener);
@@ -1013,12 +1028,17 @@ static void silc_client_ftp_resolve_cb(SilcClient client,
   }
 
   /* Parse the key agreement payload */
-  payload = silc_key_agreement_payload_parse(packet->buffer);
+  payload = silc_key_agreement_payload_parse(packet->buffer->data,
+                                            packet->buffer->len);
   if (!payload)
     goto out;
 
   hostname = silc_key_agreement_get_hostname(payload);
   port = silc_key_agreement_get_port(payload);
+  if (!hostname)
+    port = 0;
+  if (!port)
+    hostname = NULL;
 
   if (session == SILC_LIST_END || (!hostname && !port)) {
     /* No session found, create one and let the application know about
@@ -1033,8 +1053,8 @@ static void silc_client_ftp_resolve_cb(SilcClient client,
     silc_dlist_add(conn->ftp_sessions, session);
 
     /* Let the application know */
-    client->ops->ftp(client, conn, client_entry,
-                    session->session_id, hostname, port);
+    client->internal->ops->ftp(client, conn, client_entry,
+                              session->session_id, hostname, port);
 
     if (hostname && port) {
       session->hostname = strdup(hostname);