Created
July 23, 2012 22:22
-
-
Save felis-ron-silvestris/3166618 to your computer and use it in GitHub Desktop.
sendfile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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