Skip to content

Instantly share code, notes, and snippets.

@felis-ron-silvestris
Created July 23, 2012 22:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save felis-ron-silvestris/3166618 to your computer and use it in GitHub Desktop.
Save felis-ron-silvestris/3166618 to your computer and use it in GitHub Desktop.
sendfile
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sendfile.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#ifndef _MAX_SIZE_
#define _MAX_SIZE_ 80
#endif /* _MAX_SIZE_ */
#ifndef _SERVER_PORT_
#define _SERVER_PORT_ 9734
#endif /* _SERVER_PORT_ */
int err_num = 0;
/* destination address */
struct sockaddr_in dest_addr;
void send_usrname_credentials(char *usrname, int sock_fd);
void send_password_credentials(char *password, int sock_fd);
/* send file to the server */
void deliver_mail(const char *filename, int sock_fd);
/* sendfile */
ssize_t do_sendfile(int sock_fd, int input_fd, off_t offset, size_t count);
int main(int argc, char **argv)
{
if (argc != 2)
{
(void)fprintf(stderr, "Usage: %s <username>\n", argv[0]);
exit(EXIT_FAILURE);
}
/* username */
char *username = argv[1];
/* password */
char *password = NULL;
int err_num;
/* socket fd */
int socket_fd;
int length;
int string_len;
int result;
/* create the socket for the client */
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
/* checking for "socket" errors */
if (socket_fd < 0)
{
err_num = errno;
(void)fprintf(stdout, "\"socket\" error: %s\n", strerror(err_num));
exit(EXIT_FAILURE);
}
/* Initialize the socket address structure */
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
dest_addr.sin_port = htons(_SERVER_PORT_);
length = sizeof(dest_addr);
/* connect the socket to the server's socket */
result = connect(socket_fd, (struct sockaddr *)&dest_addr, length);
/* checking for "connect" errors */
if (result < 0)
{
err_num = errno;
(void)fprintf(stderr, "\"connect\" error: %s\n", strerror(err_num));
close(socket_fd);
exit(EXIT_FAILURE);
}
(void)fprintf(stdout, "Connect completed\n");
deliver_mail("mail", socket_fd);
/* send the username to the server
send_usrname_credentials(username, socket_fd);
(void)fprintf(stdout, "Utente: %s\n", username);
*/
return 0;
}
/* send the username to the server */
void send_usrname_credentials(char *usrname, int sock_fd)
{
struct msghdr username_cred;
struct iovec iov;
username_cred.msg_name = &dest_addr;
username_cred.msg_namelen = sizeof(dest_addr);
username_cred.msg_iov = &iov;
username_cred.msg_iovlen = 1;
username_cred.msg_iov->iov_base = usrname;
username_cred.msg_iov->iov_len = (strlen(usrname) + 1);
username_cred.msg_control = 0;
username_cred.msg_controllen = 0;
username_cred.msg_flags = 0;
sendmsg(sock_fd, &username_cred, 0);
}
/* send the password to the server */
void send_password_credentials(char *password, int sock_fd)
{
struct msghdr password_cred;
struct iovec iov;
password_cred.msg_name = &dest_addr;
password_cred.msg_namelen = sizeof(dest_addr);
password_cred.msg_iov = &iov;
password_cred.msg_iovlen = 1;
password_cred.msg_iov->iov_base = password;
password_cred.msg_iov->iov_len = (strlen(password) + 1);
password_cred.msg_control = 0;
password_cred.msg_controllen = 0;
password_cred.msg_flags = 0;
sendmsg(sock_fd, &password_cred, 0);
}
/* send file to the server */
void deliver_mail(const char *filename, int sock_fd)
{
/* file descriptor for file to send */
int file_descriptor;
/* argument to fstat */
struct stat stat_buf;
/* file offset */
off_t offset = 0;
int ret_val;
size_t total_bytes_sent = 0;
/* open the file to be sent */
file_descriptor = open(filename, O_RDONLY);
/* checking for "open" errors */
if (file_descriptor < 0)
{ exit(EXIT_FAILURE); }
/* get the size of the file to be sent */
fstat(file_descriptor, &stat_buf);
offset = 0;
/* sendfile */
total_bytes_sent = do_sendfile(sock_fd, file_descriptor, offset, stat_buf.st_size);
(void)fprintf(stdout, "Total bytes sent: %d\n", total_bytes_sent);
close(file_descriptor);
}
/* sendfile */
ssize_t do_sendfile(int sock_fd, int input_fd, off_t offset, size_t count)
{
ssize_t bytes_sent;
size_t total_bytes_sent = 0;
while (total_bytes_sent < count)
{
if ((bytes_sent = sendfile(sock_fd, input_fd, &offset, (count - total_bytes_sent))) <= 0)
{
if (errno == EINTR || errno == EAGAIN)
{ continue; }
err_num = errno;
(void)fprintf(stderr, "\"sendfile\" error:%s\n", strerror(err_num));
return (-1);
}
total_bytes_sent += bytes_sent;
}
return (total_bytes_sent);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment