I'm trying to learn how to use SMTP on C using Winsock. I've followed the guide provided by Microsoft, and the final code as is, works perfectly. Now, I decided to take it a step further and make it a little bit more "organized" by taking different parts of the code and put them in functions with appropiate names. I was happy to see that my code compiled succesfully, with no errors at all, but after running it for the first time, the VSC Debugger notified me of a segmentation fault. The problematic line (so far) is this one:
89| *iResult = connect( *ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
Right now I'm kinda lost, since the way you acces pointer structs dosent "add up" like with pointers, where you can have a **var1
. Maybe the error is not actually on the problematic line itself, but before... I dont know, I'm lost.
Here is my code so far:
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>
#define DEFAULT_PORT "25"
char data[500];
int initWinsock(int *, WSADATA *);
int makeSocket(int *, struct addrinfo *, struct addrinfo *, struct addrinfo *, SOCKET *);
int connSocket(int *, SOCKET *, struct addrinfo *, struct addrinfo *);
int clientReceive(int *, SOCKET *, char *);
int closeSocketListener(int *, SOCKET *);
int closeSocket(SOCKET *);
int main() {
SOCKET ConnectSocket = INVALID_SOCKET;
WSADATA wsaData;
int iResult;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
initWinsock(&iResult, &wsaData);
makeSocket(&iResult, &hints, result, ptr, &ConnectSocket);
connSocket(&iResult, &ConnectSocket, ptr, result);
clientReceive(&iResult, &ConnectSocket, data);
closeSocketListener(&iResult, &ConnectSocket);
closeSocket(&ConnectSocket);
system("pause");
return 0;
}
int initWinsock(int *iResult, WSADATA *wsaData){
// Initialize Winsock
*iResult = WSAStartup(MAKEWORD(2,2), wsaData);
if (*iResult != 0) {
printf("WSAStartup failed: %d\n", *iResult);
return 1;
}
return 0;
}
int makeSocket(int *iResult, struct addrinfo *hints, struct addrinfo *result, struct addrinfo *ptr, SOCKET *ConnectSocket){
// Resolve the server address and port
*iResult = getaddrinfo("52.97.26.134", DEFAULT_PORT, hints, &result);
if (*iResult != 0) {
printf("getaddrinfo failed: %d\n", *iResult);
WSACleanup();
return 1;
}
// Attempt to connect to the first address returned by
// the call to getaddrinfo
ptr=result;
// Create a SOCKET for connecting to server
*ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (*ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %d\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
return 0;
}
int connSocket(int *iResult, SOCKET *ConnectSocket, struct addrinfo *ptr, struct addrinfo *result){
// Connect to server.
*iResult = connect( *ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (*iResult == SOCKET_ERROR) {
closesocket(*ConnectSocket);
*ConnectSocket = INVALID_SOCKET;
}
// Should really try the next address returned by getaddrinfo
// if the connect call failed
// But for this simple example we just free the resources
// returned by getaddrinfo and print an error message
freeaddrinfo(result);
if (*ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
return 0;
}
int clientReceive(int *iResult, SOCKET *ConnectSocket, char *out){
*iResult = recv(*ConnectSocket, out, 200, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", *iResult);
return 0;
} else if (iResult == 0) {
printf("Connection closed\n");
return 1;
} else {
printf("recv failed: %d\n", WSAGetLastError());
return 2;
}
return -1;
}
int closeSocketListener(int *iResult, SOCKET *ConnectSocket){
// shutdown the send half of the connection since no more data will be sent
*iResult = shutdown(*ConnectSocket, SD_SEND);
if (*iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(*ConnectSocket);
WSACleanup();
return 1;
}
return 0;
}
int closeSocket(SOCKET *ConnectSocket){
// cleanup
closesocket(*ConnectSocket);
WSACleanup();
return 0;
}