Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
pistache
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
pistache
Commits
6c408d5c
Commit
6c408d5c
authored
Feb 06, 2019
by
ciody
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'upstream/master'
parents
8dbc68bb
2ab2b548
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
306 additions
and
197 deletions
+306
-197
include/pistache/client.h
include/pistache/client.h
+3
-4
include/pistache/net.h
include/pistache/net.h
+14
-2
include/pistache/peer.h
include/pistache/peer.h
+2
-2
include/pistache/stream.h
include/pistache/stream.h
+15
-32
include/pistache/transport.h
include/pistache/transport.h
+20
-24
src/client/client.cc
src/client/client.cc
+32
-23
src/common/http_header.cc
src/common/http_header.cc
+16
-53
src/common/net.cc
src/common/net.cc
+108
-34
src/common/peer.cc
src/common/peer.cc
+4
-4
src/common/stream.cc
src/common/stream.cc
+36
-1
src/common/transport.cc
src/common/transport.cc
+2
-12
tests/CMakeLists.txt
tests/CMakeLists.txt
+1
-0
tests/headers_test.cc
tests/headers_test.cc
+4
-0
tests/net_test.cc
tests/net_test.cc
+20
-5
tests/stream_test.cc
tests/stream_test.cc
+28
-0
tests/streaming_test.cc
tests/streaming_test.cc
+1
-1
No files found.
include/pistache/client.h
View file @
6c408d5c
...
...
@@ -30,8 +30,6 @@ namespace Http {
class
ConnectionPool
;
class
Transport
;
std
::
pair
<
StringView
,
StringView
>
splitUrl
(
const
std
::
string
&
url
);
struct
Connection
:
public
std
::
enable_shared_from_this
<
Connection
>
{
friend
class
ConnectionPool
;
...
...
@@ -96,8 +94,7 @@ struct Connection : public std::enable_shared_from_this<Connection> {
Async
::
Rejection
reject
,
OnDone
onDone
);
Fd
fd
;
Fd
fd
()
const
;
void
handleResponsePacket
(
const
char
*
buffer
,
size_t
totalBytes
);
void
handleError
(
const
char
*
error
);
void
handleTimeout
();
...
...
@@ -124,6 +121,8 @@ private:
OnDone
onDone
;
};
Fd
fd_
;
struct
sockaddr_in
saddr
;
std
::
unique_ptr
<
RequestEntry
>
requestEntry
;
std
::
atomic
<
uint32_t
>
state_
;
...
...
include/pistache/net.h
View file @
6c408d5c
...
...
@@ -12,8 +12,7 @@
#include <limits>
#include <sys/socket.h>
#include <pistache/common.h>
#include <netdb.h>
#ifndef _KERNEL_FASTOPEN
#define _KERNEL_FASTOPEN
...
...
@@ -65,6 +64,7 @@ private:
class
Port
{
public:
Port
(
uint16_t
port
=
0
);
explicit
Port
(
const
std
::
string
&
data
);
operator
uint16_t
()
const
{
return
port
;
}
...
...
@@ -123,6 +123,18 @@ private:
uint16_t
h
;
};
class
AddressParser
{
public:
explicit
AddressParser
(
const
std
::
string
&
data
);
const
std
::
string
&
rawHost
()
const
;
const
std
::
string
&
rawPort
()
const
;
int
family
()
const
;
private:
std
::
string
host_
;
std
::
string
port_
;
int
family_
;
};
class
Address
{
public:
Address
();
...
...
include/pistache/peer.h
View file @
6c408d5c
...
...
@@ -40,8 +40,8 @@ public:
Peer
(
const
Address
&
addr
);
~
Peer
()
{}
Address
address
()
const
;
std
::
string
hostname
()
const
;
const
Address
&
address
()
const
;
const
std
::
string
&
hostname
()
const
;
void
associateFd
(
Fd
fd
);
Fd
fd
()
const
;
...
...
include/pistache/stream.h
View file @
6c408d5c
...
...
@@ -6,6 +6,8 @@
#pragma once
#include <pistache/os.h>
#include <cstddef>
#include <stdexcept>
#include <cstring>
...
...
@@ -15,7 +17,6 @@
#include <iostream>
#include <string>
#include <pistache/os.h>
namespace
Pistache
{
...
...
@@ -60,7 +61,6 @@ public:
const
CharT
*
gptr
=
this
->
gptr
();
return
*
(
gptr
+
1
);
}
};
template
<
typename
CharT
=
char
>
...
...
@@ -74,7 +74,6 @@ public:
RawStreamBuf
(
char
*
begin
,
size_t
len
)
{
Base
::
setg
(
begin
,
begin
,
begin
+
len
);
}
};
// Make the buffer dynamic
...
...
@@ -123,33 +122,17 @@ private:
template
<
typename
CharT
>
size_t
ArrayStreamBuf
<
CharT
>::
maxSize
=
Const
::
DefaultMaxPayload
;
struct
Buffer
{
Buffer
()
:
data
(
nullptr
)
,
len
(
0
)
,
isOwned
(
false
)
{
}
struct
Buffer
{
Buffer
();
Buffer
(
std
::
string
data
,
int
length
,
bool
isDetached
=
false
);
Buffer
(
const
char
*
data
,
int
length
,
bool
isDetached
=
false
);
Buffer
(
const
char
*
const
_data
,
size_t
_len
,
bool
_own
=
false
)
:
data
(
_data
)
,
len
(
_len
)
,
isOwned
(
_own
)
{
}
Buffer
detach
(
size_t
fromIndex
);
Buffer
detach
(
size_t
fromIndex
=
0
)
const
{
if
(
fromIndex
>
len
)
throw
std
::
invalid_argument
(
"Invalid index (> len)"
);
size_t
retainedLen
=
len
-
fromIndex
;
char
*
newData
=
new
char
[
retainedLen
];
std
::
copy
(
data
+
fromIndex
,
data
+
len
,
newData
);
return
Buffer
(
newData
,
retainedLen
,
true
);
}
const
char
*
const
data
;
const
size_t
len
;
const
bool
isOwned
;
std
::
string
data
;
size_t
length
;
int
isDetached
;
};
struct
FileBuffer
{
...
...
@@ -165,7 +148,7 @@ struct FileBuffer {
Fd
fd
()
const
{
return
fd_
;
}
size_t
size
()
const
{
return
size_
;
}
private:
private:
std
::
string
fileName_
;
Fd
fd_
;
size_t
size_
;
...
...
@@ -206,7 +189,7 @@ public:
}
Buffer
buffer
()
const
{
return
Buffer
(
data_
.
data
(),
pptr
()
-
&
data_
[
0
]);
return
Buffer
(
(
char
*
)
data_
.
data
(),
pptr
()
-
&
data_
[
0
]);
}
void
clear
()
{
...
...
@@ -214,7 +197,7 @@ public:
this
->
setp
(
&
data_
[
0
],
&
data_
[
0
]
+
data_
.
capacity
());
}
protected:
protected:
int_type
overflow
(
int_type
ch
);
private:
...
...
@@ -261,7 +244,7 @@ public:
return
gptr
;
}
private:
private:
StreamCursor
&
cursor
;
size_t
position
;
char
*
eback
;
...
...
include/pistache/transport.h
View file @
6c408d5c
...
...
@@ -80,14 +80,14 @@ private:
enum
Type
{
Raw
,
File
};
explicit
BufferHolder
(
const
Buffer
&
buffer
,
off_t
offset
=
0
)
:
u
(
buffer
)
,
size_
(
buffer
.
len
)
:
_raw
(
buffer
)
,
size_
(
buffer
.
len
gth
)
,
offset_
(
offset
)
,
type
(
Raw
)
{
}
explicit
BufferHolder
(
const
FileBuffer
&
buffer
,
off_t
offset
=
0
)
:
u
(
buffer
.
fd
())
:
_fd
(
buffer
.
fd
())
,
size_
(
buffer
.
size
())
,
offset_
(
offset
)
,
type
(
File
)
...
...
@@ -101,44 +101,38 @@ private:
Fd
fd
()
const
{
if
(
!
isFile
())
throw
std
::
runtime_error
(
"Tried to retrieve fd of a non-filebuffer"
);
return
u
.
fd
;
return
_fd
;
}
Buffer
raw
()
const
{
if
(
!
isRaw
())
throw
std
::
runtime_error
(
"Tried to retrieve raw data of a non-buffer"
);
return
u
.
raw
;
return
_raw
;
}
BufferHolder
detach
(
size_t
offset
=
0
)
const
{
BufferHolder
detach
(
size_t
offset
=
0
)
{
if
(
!
isRaw
())
return
BufferHolder
(
u
.
fd
,
size_
,
offset
);
return
BufferHolder
(
_
fd
,
size_
,
offset
);
if
(
u
.
raw
.
isOwn
ed
)
return
BufferHolder
(
u
.
raw
,
offset
);
if
(
_raw
.
isDetach
ed
)
return
BufferHolder
(
_
raw
,
offset
);
auto
detached
=
u
.
raw
.
detach
(
offset
);
auto
detached
=
_
raw
.
detach
(
offset
);
return
BufferHolder
(
detached
);
}
private:
private:
BufferHolder
(
Fd
fd
,
size_t
size
,
off_t
offset
=
0
)
:
u
(
fd
)
:
_fd
(
fd
)
,
size_
(
size
)
,
offset_
(
offset
)
,
type
(
File
)
{
}
union
U
{
Buffer
raw
;
Fd
fd
;
Buffer
_raw
;
Fd
_fd
;
U
(
Buffer
buffer
)
:
raw
(
buffer
)
{
}
U
(
Fd
fd_
)
:
fd
(
fd_
)
{
}
}
u
;
size_t
size_
=
0
;
off_t
offset_
=
0
;
Type
type
;
...
...
@@ -225,9 +219,11 @@ private:
std
::
shared_ptr
<
Peer
>&
getPeer
(
Polling
::
Tag
tag
);
void
armTimerMs
(
Fd
fd
,
std
::
chrono
::
milliseconds
value
,
Async
::
Deferred
<
uint64_t
>
deferred
);
armTimerMs
(
Fd
fd
,
std
::
chrono
::
milliseconds
value
,
Async
::
Deferred
<
uint64_t
>
deferred
);
void
armTimerMsImpl
(
TimerEntry
entry
);
...
...
src/client/client.cc
View file @
6c408d5c
...
...
@@ -26,22 +26,25 @@ namespace Http {
static
constexpr
const
char
*
UA
=
"pistache/0.1"
;
std
::
pair
<
StringView
,
StringView
>
splitUrl
(
const
std
::
string
&
url
)
{
RawStreamBuf
<
char
>
buf
(
const_cast
<
char
*>
(
&
url
[
0
]),
url
.
size
());
StreamCursor
cursor
(
&
buf
);
namespace
{
std
::
pair
<
StringView
,
StringView
>
splitUrl
(
const
std
::
string
&
url
)
{
RawStreamBuf
<
char
>
buf
(
const_cast
<
char
*>
(
&
url
[
0
]),
url
.
size
());
StreamCursor
cursor
(
&
buf
);
match_string
(
"http://"
,
std
::
strlen
(
"http://"
),
cursor
);
match_string
(
"www"
,
std
::
strlen
(
"www"
),
cursor
);
match_literal
(
'.'
,
cursor
);
match_string
(
"http://"
,
std
::
strlen
(
"http://"
),
cursor
);
match_string
(
"www"
,
std
::
strlen
(
"www"
),
cursor
);
match_literal
(
'.'
,
cursor
);
StreamCursor
::
Token
hostToken
(
cursor
);
match_until
({
'?'
,
'/'
},
cursor
);
StreamCursor
::
Token
hostToken
(
cursor
);
match_until
({
'?'
,
'/'
},
cursor
);
StringView
host
(
hostToken
.
rawText
(),
hostToken
.
size
());
StringView
page
(
cursor
.
offset
(),
buf
.
endptr
());
StringView
host
(
hostToken
.
rawText
(),
hostToken
.
size
());
StringView
page
(
cursor
.
offset
(),
buf
.
endptr
());
return
std
::
make_pair
(
std
::
move
(
host
),
std
::
move
(
page
));
return
std
::
make_pair
(
std
::
move
(
host
),
std
::
move
(
page
));
}
}
struct
ExceptionPrinter
{
...
...
@@ -174,7 +177,7 @@ Transport::onReady(const Aio::FdSet& fds) {
// We are connected, we can start reading data now
auto
connection
=
connIt
->
second
.
connection
.
lock
();
if
(
connection
)
{
reactor
()
->
modifyFd
(
key
(),
connection
->
fd
,
NotifyOn
::
Read
);
reactor
()
->
modifyFd
(
key
(),
connection
->
fd
()
,
NotifyOn
::
Read
);
}
else
{
throw
std
::
runtime_error
(
"Connection error"
);
}
...
...
@@ -228,7 +231,7 @@ Transport::asyncSendRequestImpl(
if
(
!
conn
)
throw
std
::
runtime_error
(
"Send request error"
);
auto
fd
=
conn
->
fd
;
auto
fd
=
conn
->
fd
()
;
ssize_t
totalWritten
=
0
;
for
(;;)
{
...
...
@@ -284,17 +287,17 @@ Transport::handleConnectionQueue() {
if
(
!
conn
)
{
throw
std
::
runtime_error
(
"Connection error"
);
}
int
res
=
::
connect
(
conn
->
fd
,
data
->
getAddr
(),
data
->
addr_len
);
int
res
=
::
connect
(
conn
->
fd
()
,
data
->
getAddr
(),
data
->
addr_len
);
if
(
res
==
-
1
)
{
if
(
errno
==
EINPROGRESS
)
{
reactor
()
->
registerFdOneShot
(
key
(),
conn
->
fd
,
NotifyOn
::
Write
|
NotifyOn
::
Hangup
|
NotifyOn
::
Shutdown
);
reactor
()
->
registerFdOneShot
(
key
(),
conn
->
fd
()
,
NotifyOn
::
Write
|
NotifyOn
::
Hangup
|
NotifyOn
::
Shutdown
);
}
else
{
data
->
reject
(
Error
::
system
(
"Failed to connect"
));
continue
;
}
}
connections
.
insert
(
std
::
make_pair
(
conn
->
fd
,
std
::
move
(
*
data
)));
connections
.
insert
(
std
::
make_pair
(
conn
->
fd
()
,
std
::
move
(
*
data
)));
}
}
...
...
@@ -305,7 +308,7 @@ Transport::handleIncoming(std::shared_ptr<Connection> connection) {
ssize_t
totalBytes
=
0
;
for
(;;)
{
ssize_t
bytes
=
recv
(
connection
->
fd
,
buffer
+
totalBytes
,
Const
::
MaxBuffer
-
totalBytes
,
0
);
ssize_t
bytes
=
recv
(
connection
->
fd
()
,
buffer
+
totalBytes
,
Const
::
MaxBuffer
-
totalBytes
,
0
);
if
(
bytes
==
-
1
)
{
if
(
errno
==
EAGAIN
||
errno
==
EWOULDBLOCK
)
{
if
(
totalBytes
>
0
)
{
...
...
@@ -322,7 +325,7 @@ Transport::handleIncoming(std::shared_ptr<Connection> connection) {
}
else
{
connection
->
handleError
(
"Remote closed connection"
);
}
connections
.
erase
(
connection
->
fd
);
connections
.
erase
(
connection
->
fd
()
);
connection
->
close
();
break
;
}
...
...
@@ -348,7 +351,7 @@ Transport::handleTimeout(const std::shared_ptr<Connection>& connection) {
}
Connection
::
Connection
()
:
fd
(
-
1
)
:
fd
_
(
-
1
)
,
requestEntry
(
nullptr
)
{
state_
.
store
(
static_cast
<
uint32_t
>
(
State
::
Idle
));
...
...
@@ -382,7 +385,7 @@ Connection::connect(const Address& addr)
make_non_blocking
(
sfd
);
connectionState_
.
store
(
Connecting
);
fd
=
sfd
;
fd
_
=
sfd
;
transport_
->
asyncConnect
(
shared_from_this
(),
addr
->
ai_addr
,
addr
->
ai_addrlen
)
.
then
([
=
]()
{
...
...
@@ -402,7 +405,7 @@ Connection::connect(const Address& addr)
std
::
string
Connection
::
dump
()
const
{
std
::
ostringstream
oss
;
oss
<<
"Connection(fd = "
<<
fd
<<
", src_port = "
;
oss
<<
"Connection(fd = "
<<
fd
_
<<
", src_port = "
;
oss
<<
ntohs
(
saddr
.
sin_port
)
<<
")"
;
return
oss
.
str
();
}
...
...
@@ -420,7 +423,7 @@ Connection::isConnected() const {
void
Connection
::
close
()
{
connectionState_
.
store
(
NotConnected
);
::
close
(
fd
);
::
close
(
fd
_
);
}
void
...
...
@@ -436,6 +439,12 @@ Connection::hasTransport() const {
return
transport_
!=
nullptr
;
}
Fd
Connection
::
fd
()
const
{
assert
(
fd_
!=
-
1
);
return
fd_
;
}
void
Connection
::
handleResponsePacket
(
const
char
*
buffer
,
size_t
totalBytes
)
{
...
...
src/common/http_header.cc
View file @
6c408d5c
...
...
@@ -4,19 +4,16 @@
Implementation of common HTTP headers described by the RFC
*/
#include <stdexcept>
#include <iterator>
#include <limits>
#include <cstring>
#include <iostream>
#include <pistache/http_header.h>
#include <pistache/common.h>
#include <pistache/http.h>
#include <pistache/stream.h>
#include <arpa/inet.h>
using
namespace
std
;
#include <stdexcept>
#include <iterator>
#include <limits>
#include <cstring>
#include <iostream>
namespace
Pistache
{
namespace
Http
{
...
...
@@ -340,53 +337,19 @@ Host::Host(const std::string& data)
parse
(
data
);
}
void
Host
::
parse
(
const
std
::
string
&
data
)
{
unsigned
long
pos
=
data
.
find
(
']'
);
unsigned
long
s_pos
=
data
.
find
(
'['
);
if
(
pos
!=
std
::
string
::
npos
&&
s_pos
!=
std
::
string
::
npos
)
{
//IPv6 address
host_
=
data
.
substr
(
s_pos
,
pos
+
1
);
try
{
in6_addr
addr6
;
char
buff6
[
INET6_ADDRSTRLEN
+
1
]
=
{
0
,
};
std
::
copy
(
&
host_
[
0
],
&
host_
[
0
]
+
host_
.
size
(),
buff6
);
inet_pton
(
AF_INET6
,
buff6
,
&
(
addr6
.
s6_addr16
));
}
catch
(
std
::
runtime_error
)
{
throw
std
::
invalid_argument
(
"Invalid IPv6 address"
);
}
pos
++
;
}
else
{
//IPv4 address
pos
=
data
.
find
(
':'
);
if
(
pos
==
std
::
string
::
npos
)
{
host_
=
data
;
port_
=
HTTP_STANDARD_PORT
;
}
host_
=
data
.
substr
(
0
,
pos
);
if
(
host_
==
"*"
)
{
host_
=
"0.0.0.0"
;
}
try
{
in_addr
addr
;
char
buff
[
INET_ADDRSTRLEN
+
1
]
=
{
0
,
};
std
::
copy
(
&
host_
[
0
],
&
host_
[
0
]
+
host_
.
size
(),
buff
);
inet_pton
(
AF_INET
,
buff
,
&
(
addr
));
}
catch
(
std
::
runtime_error
)
{
throw
std
::
invalid_argument
(
"Invalid IPv4 address"
);
}
}
char
*
end
;
const
std
::
string
portPart
=
data
.
substr
(
pos
+
1
);
long
port
;
if
(
pos
!=
std
::
string
::
npos
)
{
port
=
strtol
(
portPart
.
c_str
(),
&
end
,
10
);
if
(
port
<
std
::
numeric_limits
<
uint16_t
>::
min
()
||
port
>
std
::
numeric_limits
<
uint16_t
>::
max
())
throw
std
::
invalid_argument
(
"Invalid port"
);
port_
=
static_cast
<
uint16_t
>
(
port
);
}
else
{
void
Host
::
parse
(
const
std
::
string
&
data
)
{
AddressParser
parser
(
data
);
host_
=
parser
.
rawHost
();
const
std
::
string
&
port
=
parser
.
rawPort
();
if
(
port
.
empty
())
{
port_
=
HTTP_STANDARD_PORT
;
}
else
{
port_
=
Port
(
port
);
}
}
void
...
...
src/common/net.cc
View file @
6c408d5c
...
...
@@ -3,6 +3,9 @@
*/
#include <pistache/net.h>
#include <pistache/common.h>
#include <stdexcept>
#include <limits>
#include <cstring>
...
...
@@ -12,16 +15,42 @@
#include <ifaddrs.h>
#include <iostream>
#include <pistache/net.h>
#include <pistache/common.h>
namespace
Pistache
{
using
namespace
std
;
namespace
{
bool
IsIPv4HostName
(
const
std
::
string
&
host
)
{
in_addr
addr
;
char
buff
[
INET_ADDRSTRLEN
+
1
]
=
{
0
,
};
std
::
copy
(
host
.
begin
(),
host
.
end
(),
buff
);
int
res
=
inet_pton
(
AF_INET
,
buff
,
&
addr
);
return
res
;
}
namespace
Pistache
{
bool
IsIPv6HostName
(
const
std
::
string
&
host
)
{
in6_addr
addr6
;
char
buff6
[
INET6_ADDRSTRLEN
+
1
]
=
{
0
,
};
std
::
copy
(
host
.
begin
(),
host
.
end
(),
buff6
);
int
res
=
inet_pton
(
AF_INET6
,
buff6
,
&
(
addr6
.
s6_addr16
));
return
res
;
}
}
Port
::
Port
(
uint16_t
port
)
:
port
(
port
)
{
}
{}
Port
::
Port
(
const
std
::
string
&
data
)
{
if
(
data
.
empty
())
throw
std
::
invalid_argument
(
"Invalid port: empty port"
);
char
*
end
=
0
;
long
port_num
=
strtol
(
data
.
c_str
(),
&
end
,
10
);
if
(
*
end
!=
0
||
port_num
<
Port
::
min
()
||
port_num
>
Port
::
max
())
throw
std
::
invalid_argument
(
"Invalid port: "
+
data
);
port
=
static_cast
<
uint16_t
>
(
port_num
);
}
bool
Port
::
isReserved
()
const
{
...
...
@@ -157,6 +186,48 @@ bool Ipv6::supported() {
return
supportsIpv6
;
}
AddressParser
::
AddressParser
(
const
std
::
string
&
data
)
{
std
::
size_t
end_pos
=
data
.
find
(
']'
);
std
::
size_t
start_pos
=
data
.
find
(
'['
);
if
(
start_pos
!=
std
::
string
::
npos
&&
end_pos
!=
std
::
string
::
npos
&&
start_pos
<
end_pos
)
{
host_
=
data
.
substr
(
start_pos
,
end_pos
+
1
);
family_
=
AF_INET6
;
++
end_pos
;
}
else
{
end_pos
=
data
.
find
(
':'
);
host_
=
data
.
substr
(
0
,
end_pos
);
family_
=
AF_INET
;
}
if
(
end_pos
!=
std
::
string
::
npos
)
{
port_
=
data
.
substr
(
end_pos
+
1
);
if
(
port_
.
empty
())
throw
std
::
invalid_argument
(
"Invalid port"
);
}
}
const
std
::
string
&
AddressParser
::
rawHost
()
const
{
return
host_
;
}
const
std
::
string
&
AddressParser
::
rawPort
()
const
{
return
port_
;
}
int
AddressParser
::
family
()
const
{
return
family_
;
}
Address
::
Address
()
:
host_
(
""
)
,
port_
(
0
)
...
...
@@ -228,46 +299,49 @@ Address::family() const {
return
family_
;
}
void
Address
::
init
(
const
std
::
string
&
addr
)
{
unsigned
long
pos
=
addr
.
find
(
']'
);
unsigned
long
s_pos
=
addr
.
find
(
'['
);
if
(
pos
!=
std
::
string
::
npos
&&
s_pos
!=
std
::
string
::
npos
)
{
//IPv6 address
host_
=
addr
.
substr
(
s_pos
+
1
,
pos
-
1
);
family_
=
AF_INET6
;
try
{
in6_addr
addr6
;
inet_pton
(
AF_INET6
,
host_
.
c_str
(),
&
(
addr6
.
s6_addr16
));
}
catch
(
std
::
runtime_error
)
{
void
Address
::
init
(
const
std
::
string
&
addr
)
{
AddressParser
parser
(
addr
);
family_
=
parser
.
family
(
);
if
(
family_
==
AF_INET6
)
{
const
std
::
string
&
raw_host
=
parser
.
rawHost
(
);
assert
(
raw_host
.
size
()
>
2
)
;
host_
=
addr
.
substr
(
1
,
raw_host
.
size
()
-
2
);
if
(
!
IsIPv6HostName
(
host_
))
{
throw
std
::
invalid_argument
(
"Invalid IPv6 address"
);
}
pos
++
;
}
else
{
//IPv4 address
pos
=
addr
.
find
(
':'
);
if
(
pos
==
std
::
string
::
npos
)
throw
std
::
invalid_argument
(
"Invalid address"
);
host_
=
addr
.
substr
(
0
,
pos
);
family_
=
AF_INET
;
if
(
host_
==
"*"
)
{
}
else
if
(
family_
==
AF_INET
)
{
host_
=
parser
.
rawHost
();
if
(
host_
==
"*"
)
{
host_
=
"0.0.0.0"
;
}
try
{
in_addr
addr
;
inet_pton
(
AF_INET
,
host_
.
c_str
(),
&
(
addr
));
}
catch
(
std
::
runtime_error
)
{
else
if
(
host_
==
"localhost"
)
{
host_
=
"127.0.0.1"
;
}
if
(
!
IsIPv4HostName
(
host_
))
{
throw
std
::
invalid_argument
(
"Invalid IPv4 address"
);
}
}
char
*
end
;
const
std
::
string
portPart
=
addr
.
substr
(
pos
+
1
);
else
{
assert
(
false
);
}
const
std
::
string
&
portPart
=
parser
.
rawPort
();
if
(
portPart
.
empty
())
throw
std
::
invalid_argument
(
"Invalid port"
);
throw
std
::
invalid_argument
(
"Invalid port"
);
char
*
end
=
0
;
long
port
=
strtol
(
portPart
.
c_str
(),
&
end
,
10
);
if
(
*
end
!=
0
||
port
<
Port
::
min
()
||
port
>
Port
::
max
())
throw
std
::
invalid_argument
(
"Invalid port"
);
port_
=
static_cast
<
uint16_t
>
(
port
);
port_
=
Port
(
port
);
}
Error
::
Error
(
const
char
*
message
)
...
...
src/common/peer.cc
View file @
6c408d5c
...
...
@@ -30,13 +30,13 @@ Peer::Peer(const Address& addr)
,
ssl_
(
NULL
)
{
}
Address
Peer
::
address
()
const
{
const
Address
&
Peer
::
address
()
const
{
return
addr
;
}
string
Peer
::
hostname
()
const
{
const
std
::
string
&
Peer
::
hostname
()
const
{
return
hostname_
;
}
...
...
src/common/stream.cc
View file @
6c408d5c
...
...
@@ -3,6 +3,8 @@
*/
#include <pistache/stream.h>
#include <iostream>
#include <algorithm>
#include <string>
...
...
@@ -12,10 +14,43 @@
#include <unistd.h>
#include <fcntl.h>
#include <pistache/stream.h>
namespace
Pistache
{
Buffer
::
Buffer
()
:
data
()
,
length
(
0
)
,
isDetached
(
false
)
{
}
Buffer
::
Buffer
(
std
::
string
data
,
int
length
,
bool
isDetached
)
:
data
(
std
::
move
(
data
))
,
length
(
length
)
,
isDetached
(
isDetached
)
{
}
Buffer
::
Buffer
(
const
char
*
data
,
int
length
,
bool
isDetached
)
:
data
()
,
length
(
length
)
,
isDetached
(
isDetached
)
{
this
->
data
.
resize
(
length
+
1
);
this
->
data
.
assign
(
data
,
length
+
1
);
}
Buffer
Buffer
::
detach
(
size_t
fromIndex
)
{
if
(
data
.
empty
())
return
Buffer
();
if
(
length
<
fromIndex
)
throw
std
::
range_error
(
"Trying to detach buffer from an index bigger than lengthght."
);
auto
newDatalength
=
length
-
fromIndex
;
std
::
string
newData
=
data
.
substr
(
fromIndex
,
newDatalength
);
return
Buffer
(
std
::
move
(
newData
),
newDatalength
,
true
);
}
FileBuffer
::
FileBuffer
(
const
std
::
string
&
fileName
)
:
fileName_
(
fileName
)
...
...
src/common/transport.cc
View file @
6c408d5c
...
...
@@ -192,12 +192,6 @@ Transport::handlePeerDisconnection(const std::shared_ptr<Peer>& peer) {
Guard
guard
(
toWriteLock
);
auto
&
wq
=
toWrite
[
fd
];
while
(
wq
.
size
()
>
0
)
{
auto
&
entry
=
wq
.
front
();
const
BufferHolder
&
buffer
=
entry
.
buffer
;
if
(
buffer
.
isRaw
())
{
auto
raw
=
buffer
.
raw
();
if
(
raw
.
isOwned
)
delete
[]
raw
.
data
;
}
wq
.
pop_front
();
}
toWrite
.
erase
(
fd
);
...
...
@@ -224,14 +218,10 @@ Transport::asyncWriteImpl(Fd fd)
auto
&
entry
=
wq
.
front
();
int
flags
=
entry
.
flags
;
const
BufferHolder
&
buffer
=
entry
.
buffer
;
BufferHolder
&
buffer
=
entry
.
buffer
;
Async
::
Deferred
<
ssize_t
>
deferred
=
std
::
move
(
entry
.
deferred
);
auto
cleanUp
=
[
&
]()
{
if
(
buffer
.
isRaw
())
{
auto
raw
=
buffer
.
raw
();
if
(
raw
.
isOwned
)
delete
[]
raw
.
data
;
}
wq
.
pop_front
();
if
(
wq
.
size
()
==
0
)
{
toWrite
.
erase
(
fd
);
...
...
@@ -247,7 +237,7 @@ Transport::asyncWriteImpl(Fd fd)
if
(
buffer
.
isRaw
())
{
auto
raw
=
buffer
.
raw
();
auto
ptr
=
raw
.
data
+
totalWritten
;
auto
ptr
=
raw
.
data
.
c_str
()
+
totalWritten
;
#ifdef PISTACHE_USE_SSL
auto
it
=
peers
.
find
(
fd
);
...
...
tests/CMakeLists.txt
View file @
6c408d5c
...
...
@@ -28,6 +28,7 @@ pistache_test(streaming_test)
pistache_test
(
rest_server_test
)
pistache_test
(
string_view_test
)
pistache_test
(
mailbox_test
)
pistache_test
(
stream_test
)
if
(
PISTACHE_SSL
)
...
...
tests/headers_test.cc
View file @
6c408d5c
...
...
@@ -256,6 +256,10 @@ TEST(headers_test, host) {
ASSERT_EQ
(
host
.
host
(),
"www.w3.org"
);
ASSERT_EQ
(
host
.
port
(),
80
);
host
.
parse
(
"www.example.com:8080"
);
ASSERT_EQ
(
host
.
host
(),
"www.example.com"
);
ASSERT_EQ
(
host
.
port
(),
8080
);
host
.
parse
(
"localhost:8080"
);
ASSERT_EQ
(
host
.
host
(),
"localhost"
);
ASSERT_EQ
(
host
.
port
(),
8080
);
...
...
tests/net_test.cc
View file @
6c408d5c
...
...
@@ -90,9 +90,24 @@ TEST(net_test, invalid_address)
ASSERT_THROW
(
Address
(
"127.0.0.1:"
),
std
::
invalid_argument
);
ASSERT_THROW
(
Address
(
"127.0.0.1:-10"
),
std
::
invalid_argument
);
/* Due to an error in GLIBC these tests don't fail as expected, further research needed */
// ASSERT_THROW(Address("[GGGG:GGGG:GGGG:GGGG:GGGG:GGGG:GGGG:GGGG]:8080");, std::invalid_argument);
// ASSERT_THROW(Address("[::GGGG]:8080");, std::invalid_argument);
// ASSERT_THROW(Address("256.256.256.256:8080");, std::invalid_argument);
// ASSERT_THROW(Address("1.0.0.256:8080");, std::invalid_argument);
ASSERT_THROW
(
Address
(
"[GGGG:GGGG:GGGG:GGGG:GGGG:GGGG:GGGG:GGGG]:8080"
);,
std
::
invalid_argument
);
ASSERT_THROW
(
Address
(
"[::GGGG]:8080"
);,
std
::
invalid_argument
);
ASSERT_THROW
(
Address
(
"256.256.256.256:8080"
);,
std
::
invalid_argument
);
ASSERT_THROW
(
Address
(
"1.0.0.256:8080"
);,
std
::
invalid_argument
);
}
TEST
(
net_test
,
address_parser
)
{
AddressParser
ap1
(
"127.0.0.1:80"
);
ASSERT_EQ
(
ap1
.
rawHost
(),
"127.0.0.1"
);
ASSERT_EQ
(
ap1
.
rawPort
(),
"80"
);
ASSERT_EQ
(
ap1
.
family
(),
AF_INET
);
AddressParser
ap2
(
"[2001:0DB8:AABB:CCDD:EEFF:0011:2233:4455]:8080"
);
ASSERT_EQ
(
ap2
.
rawHost
(),
"[2001:0DB8:AABB:CCDD:EEFF:0011:2233:4455]"
);
ASSERT_EQ
(
ap2
.
rawPort
(),
"8080"
);
ASSERT_EQ
(
ap2
.
family
(),
AF_INET6
);
ASSERT_THROW
(
AddressParser
(
"127.0.0.1:"
);,
std
::
invalid_argument
);
ASSERT_THROW
(
AddressParser
(
"[::]:"
);,
std
::
invalid_argument
);
}
tests/stream_test.cc
0 → 100644
View file @
6c408d5c
#include <pistache/stream.h>
#include "gtest/gtest.h"
#include <cstring>
using
namespace
Pistache
;
TEST
(
stream
,
test_buffer
)
{
char
str
[]
=
"test_string"
;
size_t
len
=
strlen
(
str
);
Buffer
buffer1
(
str
,
len
,
false
);
Buffer
buffer2
=
buffer1
.
detach
(
0
);
ASSERT_EQ
(
buffer2
.
length
,
len
);
ASSERT_EQ
(
buffer2
.
isDetached
,
true
);
Buffer
buffer3
;
ASSERT_EQ
(
buffer3
.
length
,
0u
);
ASSERT_EQ
(
buffer3
.
isDetached
,
false
);
Buffer
buffer4
=
buffer3
.
detach
(
0
);
ASSERT_EQ
(
buffer4
.
length
,
0u
);
ASSERT_EQ
(
buffer4
.
isDetached
,
false
);
ASSERT_THROW
(
buffer1
.
detach
(
2
*
len
);,
std
::
range_error
);
}
\ No newline at end of file
tests/streaming_test.cc
View file @
6c408d5c
...
...
@@ -46,7 +46,7 @@ void dumpData(const Rest::Request&req, Http::ResponseWriter response) {
stream
.
ends
();
}
TEST
(
stream
,
from_description
)
TEST
(
stream
ing
,
from_description
)
{
Address
addr
(
Ipv4
::
any
(),
Port
(
0
));
const
size_t
threads
=
20
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment