Merge branch 'master' of git://factorcode.org/git/factor
commit
061bcbb8eb
|
@ -89,11 +89,6 @@ set_md5sum() {
|
||||||
set_gcc() {
|
set_gcc() {
|
||||||
case $OS in
|
case $OS in
|
||||||
openbsd) ensure_program_installed egcc; CC=egcc;;
|
openbsd) ensure_program_installed egcc; CC=egcc;;
|
||||||
netbsd) if [[ $WORD -eq 64 ]] ; then
|
|
||||||
CC=/usr/pkg/gcc34/bin/gcc
|
|
||||||
else
|
|
||||||
CC=gcc
|
|
||||||
fi ;;
|
|
||||||
*) CC=gcc;;
|
*) CC=gcc;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ IN: alarms
|
||||||
USING: help.markup help.syntax calendar quotations ;
|
USING: help.markup help.syntax calendar quotations ;
|
||||||
|
|
||||||
HELP: alarm
|
HELP: alarm
|
||||||
{ $class-description "An alarm. Cancel passed to " { $link cancel-alarm } "." } ;
|
{ $class-description "An alarm. Can be passed to " { $link cancel-alarm } "." } ;
|
||||||
|
|
||||||
HELP: add-alarm
|
HELP: add-alarm
|
||||||
{ $values { "quot" quotation } { "time" timestamp } { "frequency" "a " { $link duration } " or " { $link f } } { "alarm" alarm } }
|
{ $values { "quot" quotation } { "time" timestamp } { "frequency" "a " { $link duration } " or " { $link f } } { "alarm" alarm } }
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
IN: db.pooling.tests
|
|
||||||
USING: db.pooling tools.test ;
|
|
||||||
|
|
||||||
\ <pool> must-infer
|
|
||||||
|
|
||||||
{ 2 0 } [ [ ] with-db-pool ] must-infer-as
|
|
||||||
|
|
||||||
{ 1 0 } [ [ ] with-pooled-connection ] must-infer-as
|
|
|
@ -1,43 +0,0 @@
|
||||||
! Copyright (C) 2008 Slava Pestov.
|
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
|
||||||
USING: accessors kernel arrays namespaces sequences continuations
|
|
||||||
destructors db ;
|
|
||||||
IN: db.pooling
|
|
||||||
|
|
||||||
TUPLE: pool db params connections ;
|
|
||||||
|
|
||||||
: <pool> ( db params -- pool )
|
|
||||||
V{ } clone pool boa ;
|
|
||||||
|
|
||||||
M: pool dispose [ dispose-each f ] change-connections drop ;
|
|
||||||
|
|
||||||
: with-db-pool ( db params quot -- )
|
|
||||||
>r <pool> r> [ pool swap with-variable ] curry with-disposal ; inline
|
|
||||||
|
|
||||||
TUPLE: return-connection db pool ;
|
|
||||||
|
|
||||||
: return-connection ( db pool -- )
|
|
||||||
connections>> push ;
|
|
||||||
|
|
||||||
: new-connection ( pool -- )
|
|
||||||
[ [ db>> ] [ params>> ] bi make-db db-open ] keep
|
|
||||||
return-connection ;
|
|
||||||
|
|
||||||
: acquire-connection ( pool -- db )
|
|
||||||
[ dup connections>> empty? ] [ dup new-connection ] [ ] while
|
|
||||||
connections>> pop ;
|
|
||||||
|
|
||||||
: (with-pooled-connection) ( db pool quot -- )
|
|
||||||
[ >r drop db r> with-variable ]
|
|
||||||
[ drop return-connection ]
|
|
||||||
3bi ; inline
|
|
||||||
|
|
||||||
: with-pooled-connection ( pool quot -- )
|
|
||||||
>r [ acquire-connection ] keep r>
|
|
||||||
[ (with-pooled-connection) ] [ ] [ 2drop dispose ] cleanup ; inline
|
|
||||||
|
|
||||||
M: return-connection dispose
|
|
||||||
[ db>> ] [ pool>> ] bi return-connection ;
|
|
||||||
|
|
||||||
: return-connection-later ( db pool -- )
|
|
||||||
\ return-connection boa &dispose drop ;
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
IN: db.pools.tests
|
||||||
|
USING: db.pools tools.test ;
|
||||||
|
|
||||||
|
\ <db-pool> must-infer
|
||||||
|
|
||||||
|
{ 2 0 } [ [ ] with-db-pool ] must-infer-as
|
||||||
|
|
||||||
|
{ 1 0 } [ [ ] with-pooled-db ] must-infer-as
|
|
@ -0,0 +1,21 @@
|
||||||
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: accessors kernel arrays namespaces sequences continuations
|
||||||
|
io.pools db ;
|
||||||
|
IN: db.pools
|
||||||
|
|
||||||
|
TUPLE: db-pool < pool db params ;
|
||||||
|
|
||||||
|
: <db-pool> ( db params -- pool )
|
||||||
|
db-pool <pool>
|
||||||
|
swap >>params
|
||||||
|
swap >>db ;
|
||||||
|
|
||||||
|
: with-db-pool ( db params quot -- )
|
||||||
|
>r <db-pool> r> with-pool ; inline
|
||||||
|
|
||||||
|
M: db-pool make-connection ( pool -- )
|
||||||
|
[ db>> ] [ params>> ] bi make-db db-open ;
|
||||||
|
|
||||||
|
: with-pooled-db ( pool quot -- )
|
||||||
|
[ db swap with-variable ] curry with-pooled-connection ; inline
|
|
@ -0,0 +1 @@
|
||||||
|
network
|
|
@ -0,0 +1 @@
|
||||||
|
network
|
|
@ -0,0 +1 @@
|
||||||
|
network
|
|
@ -1,4 +1,4 @@
|
||||||
USING: alien alien.c-types kernel math sequences strings
|
USING: unix alien alien.c-types kernel math sequences strings
|
||||||
io.unix.backend splitting ;
|
io.unix.backend splitting ;
|
||||||
IN: hardware-info.linux
|
IN: hardware-info.linux
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
! Copyright (C) 2008 Slava Pestov.
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: db db.pooling http.server http.server.sessions kernel
|
USING: db db.pools io.pools http.server http.server.sessions
|
||||||
accessors continuations namespaces destructors ;
|
kernel accessors continuations namespaces destructors ;
|
||||||
IN: http.server.db
|
IN: http.server.db
|
||||||
|
|
||||||
TUPLE: db-persistence < filter-responder pool ;
|
TUPLE: db-persistence < filter-responder pool ;
|
||||||
|
|
||||||
: <db-persistence> ( responder db params -- responder' )
|
: <db-persistence> ( responder db params -- responder' )
|
||||||
<pool> db-persistence boa ;
|
<db-pool> db-persistence boa ;
|
||||||
|
|
||||||
M: db-persistence call-responder*
|
M: db-persistence call-responder*
|
||||||
[
|
[
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Slava Pestov
|
|
@ -0,0 +1,61 @@
|
||||||
|
IN: io.pools
|
||||||
|
USING: help.markup help.syntax destructors quotations ;
|
||||||
|
|
||||||
|
HELP: pool
|
||||||
|
{ $class-description "A connection pool. Instances of this class are not intended to be instantiated directly, only subclasses should be instantiated, for example " { $link datagram-pool } "." } ;
|
||||||
|
|
||||||
|
HELP: <pool>
|
||||||
|
{ $values { "class" "a subclass of " { $link pool } } { "pool" pool } }
|
||||||
|
{ $description "Creates a new connection pool." }
|
||||||
|
{ $notes "To avoid resource leaks, pools must be disposed of by calling " { $link dispose } " when no longer in use." } ;
|
||||||
|
|
||||||
|
HELP: with-pool
|
||||||
|
{ $values { "pool" pool } { "quot" quotation } }
|
||||||
|
{ $description "Calls a quotation in a new dynamic scope with the " { $link pool } " variable set to " { $snippet "pool" } ". The pool is disposed of after the quotation returns, or if an error is thrown." } ;
|
||||||
|
|
||||||
|
HELP: acquire-connection
|
||||||
|
{ $values { "pool" pool } { "conn" "a connection" } }
|
||||||
|
{ $description "Outputs a connection from the pool, preferring to take an existing one, creating a new one with " { $link make-connection } " if the pool is empty." } ;
|
||||||
|
|
||||||
|
HELP: return-connection
|
||||||
|
{ $values { "conn" "a connection" } { "pool" pool } }
|
||||||
|
{ $description "Returns a connection to the pool." } ;
|
||||||
|
|
||||||
|
HELP: with-pooled-connection
|
||||||
|
{ $values { "pool" pool } { "quot" "a quotation with stack effect " { $snippet "( conn -- )" } } }
|
||||||
|
{ $description "Calls a quotation with a pooled connection on the stack. If the quotation returns successfully, the connection is returned to the pool; if the quotation throws an error, the connection is disposed of with " { $link dispose } "." } ;
|
||||||
|
|
||||||
|
HELP: make-connection
|
||||||
|
{ $values { "pool" pool } { "conn" "a connection" } }
|
||||||
|
{ $contract "Makes a connection for the pool." } ;
|
||||||
|
|
||||||
|
HELP: datagram-pool
|
||||||
|
{ $class-description "A pool of datagram sockets bound to the address stored in the " { $snippet "addrspec" } " slot." } ;
|
||||||
|
|
||||||
|
HELP: <datagram-pool>
|
||||||
|
{ $values { "addrspec" "an address specifier" } { "pool" datagram-pool } }
|
||||||
|
{ $description "Creates a new " { $link datagram-pool } ". The port number of the " { $snippet "addrspec" } " should be 0, otherwise creation of more than one datagram socket will raise an error." }
|
||||||
|
{ $examples
|
||||||
|
{ $code "f 0 <inet4> <datagram-pool>" }
|
||||||
|
} ;
|
||||||
|
|
||||||
|
ARTICLE: "io.pools" "Connection pools"
|
||||||
|
"Connection pools are implemented in the " { $snippet "io.pools" } " vocabulary. They are used to reuse sockets and connections which may be potentially expensive to create and destroy."
|
||||||
|
$nl
|
||||||
|
"The class of connection pools:"
|
||||||
|
{ $subsection pool }
|
||||||
|
"Creating connection pools:"
|
||||||
|
{ $subsection <pool> }
|
||||||
|
"A utility combinator:"
|
||||||
|
{ $subsection with-pool }
|
||||||
|
"Acquiring and returning connections, and a utility combinator:"
|
||||||
|
{ $subsection acquire-connection }
|
||||||
|
{ $subsection return-connection }
|
||||||
|
{ $subsection with-pooled-connection }
|
||||||
|
"Pools are not created directly, instead one uses subclasses which implement a generic word:"
|
||||||
|
{ $subsection make-connection }
|
||||||
|
"One example is a datagram socket pool:"
|
||||||
|
{ $subsection datagram-pool }
|
||||||
|
{ $subsection <datagram-pool> } ;
|
||||||
|
|
||||||
|
ABOUT: "io.pools"
|
|
@ -0,0 +1,50 @@
|
||||||
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: accessors kernel arrays namespaces sequences continuations
|
||||||
|
destructors io.sockets ;
|
||||||
|
IN: io.pools
|
||||||
|
|
||||||
|
TUPLE: pool connections disposed ;
|
||||||
|
|
||||||
|
: <pool> ( class -- pool )
|
||||||
|
new V{ } clone >>connections ; inline
|
||||||
|
|
||||||
|
M: pool dispose* connections>> dispose-each ;
|
||||||
|
|
||||||
|
: with-pool ( pool quot -- )
|
||||||
|
[ pool swap with-variable ] curry with-disposal ; inline
|
||||||
|
|
||||||
|
TUPLE: return-connection conn pool ;
|
||||||
|
|
||||||
|
: return-connection ( conn pool -- )
|
||||||
|
dup check-disposed connections>> push ;
|
||||||
|
|
||||||
|
GENERIC: make-connection ( pool -- conn )
|
||||||
|
|
||||||
|
: new-connection ( pool -- )
|
||||||
|
[ make-connection ] keep return-connection ;
|
||||||
|
|
||||||
|
: acquire-connection ( pool -- conn )
|
||||||
|
dup check-disposed
|
||||||
|
[ dup connections>> empty? ] [ dup new-connection ] [ ] while
|
||||||
|
connections>> pop ;
|
||||||
|
|
||||||
|
: (with-pooled-connection) ( conn pool quot -- )
|
||||||
|
[ nip call ] [ drop return-connection ] 3bi ; inline
|
||||||
|
|
||||||
|
: with-pooled-connection ( pool quot -- )
|
||||||
|
>r [ acquire-connection ] keep r>
|
||||||
|
[ (with-pooled-connection) ] [ ] [ 2drop dispose ] cleanup ; inline
|
||||||
|
|
||||||
|
M: return-connection dispose
|
||||||
|
[ conn>> ] [ pool>> ] bi return-connection ;
|
||||||
|
|
||||||
|
: return-connection-later ( db pool -- )
|
||||||
|
\ return-connection boa &dispose drop ;
|
||||||
|
|
||||||
|
TUPLE: datagram-pool < pool addrspec ;
|
||||||
|
|
||||||
|
: <datagram-pool> ( addrspec -- pool )
|
||||||
|
datagram-pool <pool> swap >>addrspec ;
|
||||||
|
|
||||||
|
M: datagram-pool make-connection addrspec>> <datagram> ;
|
|
@ -0,0 +1 @@
|
||||||
|
Abstract connection pooling
|
|
@ -0,0 +1 @@
|
||||||
|
network
|
|
@ -0,0 +1 @@
|
||||||
|
network
|
|
@ -0,0 +1 @@
|
||||||
|
Slava Pestov
|
|
@ -0,0 +1,125 @@
|
||||||
|
IN: io.sockets.secure
|
||||||
|
USING: help.markup help.syntax calendar quotations io.sockets ;
|
||||||
|
|
||||||
|
HELP: secure-socket-timeout
|
||||||
|
{ $var-description "Timeout for operations not associated with a constructed port instance, such as SSL handshake and shutdown. Represented as a " { $link duration } "." } ;
|
||||||
|
|
||||||
|
HELP: SSLv2
|
||||||
|
{ $description "Possible value for the " { $snippet "method" } " slot of a " { $link secure-config } "."
|
||||||
|
$nl
|
||||||
|
"Note that the SSLv2 protocol is vulnerable to truncation attacks and its use is discouraged (" { $url "http://www.gnu.org/software/gnutls/manual/html_node/On-SSL-2-and-older-protocols.html" } ")." } ;
|
||||||
|
|
||||||
|
HELP: SSLv3
|
||||||
|
{ $description "Possible value for the " { $snippet "method" } " slot of a " { $link secure-config } "."
|
||||||
|
$nl
|
||||||
|
"SSLv3 is widely used, however it is being supersceded by TLSv1." } ;
|
||||||
|
|
||||||
|
HELP: SSLv23
|
||||||
|
{ $description "Possible value for the " { $snippet "method" } " slot of a " { $link secure-config } "."
|
||||||
|
$nl
|
||||||
|
"This value indicates that either SSLv2 or SSLv3 is acceptable." } ;
|
||||||
|
|
||||||
|
HELP: TLSv1
|
||||||
|
{ $description "Possible value for the " { $snippet "method" } " slot of a " { $link secure-config } "."
|
||||||
|
$nl
|
||||||
|
"TLSv1 is the newest protocol for secure socket communications." } ;
|
||||||
|
|
||||||
|
ARTICLE: "ssl-methods" "SSL/TLS methods"
|
||||||
|
"The " { $snippet "method" } " slot of a " { $link secure-config } " can be set to one of the following values:"
|
||||||
|
{ $subsection SSLv2 }
|
||||||
|
{ $subsection SSLv23 }
|
||||||
|
{ $subsection SSLv3 }
|
||||||
|
{ $subsection TLSv1 }
|
||||||
|
"The default value is " { $link SSLv23 } "." ;
|
||||||
|
|
||||||
|
HELP: secure-config
|
||||||
|
{ $class-description "Instances represent secure socket configurations." } ;
|
||||||
|
|
||||||
|
HELP: <secure-config>
|
||||||
|
{ $values { "config" secure-config } }
|
||||||
|
{ $description "Creates a new secure socket configration with default values." } ;
|
||||||
|
|
||||||
|
ARTICLE: "ssl-key-file" "The key file and password"
|
||||||
|
"The " { $snippet "key-file" } " and " { $snippet "password" } " slots of a " { $link secure-config } " can be set to a private key file in PEM format. These slots are required for secure servers, and also for clients when client-side authentication is used." ;
|
||||||
|
|
||||||
|
ARTICLE: "ssl-ca-file" "The CA file and path"
|
||||||
|
"The " { $snippet "ca-file" } " slot of a " { $link secure-config } " can contain the path of a file with a list of trusted certificates in PEM format. The " { $snippet "ca-path" } " slot can contain the path of a directory of trusted certifications."
|
||||||
|
$nl
|
||||||
|
"One of these slots are required to be specified so that secure client sockets can verify server certificates."
|
||||||
|
$nl
|
||||||
|
"See " { $url "http://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html" } " for details." ;
|
||||||
|
|
||||||
|
ARTICLE: "ssl-dh-file" "Diffie-Hellman parameter file"
|
||||||
|
"The " { $snippet "dh-file" } " slot of a " { $link secure-config } " can contain the path of a file with Diffie-Hellman key exchange parameters."
|
||||||
|
$nl
|
||||||
|
"This slot is required for secure server sockets." ;
|
||||||
|
|
||||||
|
ARTICLE: "ssl-ephemeral-rsa" "Ephemeral RSA key bits"
|
||||||
|
"The " { $snippet "ephemeral-key-bits" } " slot of a " { $link secure-config } " contains the length of the empheral RSA key, in bits."
|
||||||
|
$nl
|
||||||
|
"The default value is 1024, and anything less than that is considered insecure. This slot is required for secure server sockets." ;
|
||||||
|
|
||||||
|
ARTICLE: "ssl-config" "Secure socket configuration"
|
||||||
|
"Secure sockets require some configuration, particularly for server sockets. A class represents secure socket configuration parameters:"
|
||||||
|
{ $subsection secure-config }
|
||||||
|
"Creating new instances:"
|
||||||
|
{ $subsection <secure-config> }
|
||||||
|
"Configuration parameters:"
|
||||||
|
{ $subsection "ssl-methods" }
|
||||||
|
{ $subsection "ssl-key-file" }
|
||||||
|
{ $subsection "ssl-ca-file" }
|
||||||
|
{ $subsection "ssl-dh-file" }
|
||||||
|
{ $subsection "ssl-ephemeral-rsa" } ;
|
||||||
|
|
||||||
|
HELP: <secure-context>
|
||||||
|
{ $values { "config" secure-config } { "context" secure-context } }
|
||||||
|
{ $description "Creates a new " { $link secure-context } ". This word should not usually be called directly, use " { $link with-secure-context } " instead." } ;
|
||||||
|
|
||||||
|
HELP: with-secure-context
|
||||||
|
{ $values { "config" secure-config } { "quot" quotation } }
|
||||||
|
{ $description "Calls the quotation in a new dynamic scope where a " { $link secure-context } " constructed from the specified configuration is available." } ;
|
||||||
|
|
||||||
|
ARTICLE: "ssl-contexts" "Secure socket contexts"
|
||||||
|
"All secure socket operations must be performed in a secure socket context. A context is created from a secure socket configuration. An implicit context with the default configuration is always available, however server sockets require a certificate to be set together with other parameters, and the default configuration is insufficient, so a context must be explicitly created in that case."
|
||||||
|
{ $subsection with-secure-context } ;
|
||||||
|
|
||||||
|
HELP: secure
|
||||||
|
{ $class-description "The class of secure socket addresses." } ;
|
||||||
|
|
||||||
|
HELP: <secure> ( addrspec -- secure )
|
||||||
|
{ $values { "addrspec" "an address specifier" } { "secure" secure } }
|
||||||
|
{ $description "Creates a new secure socket address, which can then be passed to " { $link <client> } " or " { $link <server> } "." } ;
|
||||||
|
|
||||||
|
ARTICLE: "ssl-addresses" "Secure socket addresses"
|
||||||
|
"Secure socket connections are established by passing a secure socket address to " { $link <client> } " or " { $link <server> } "."
|
||||||
|
$nl
|
||||||
|
"Secure socket addresses form a class:"
|
||||||
|
{ $subsection secure }
|
||||||
|
"Constructing secure socket addresses:"
|
||||||
|
{ $subsection <secure> }
|
||||||
|
"Instances of this class can wrap an " { $link inet } ", " { $link inet4 } " or an " { $link inet6 } ", although note that certificate validation is only performed for instances of " { $link inet } " since otherwise the host name is not available." ;
|
||||||
|
|
||||||
|
HELP: premature-close
|
||||||
|
{ $error-description "Thrown if an SSL connection is closed without the proper " { $snippet "close_notify" } " sequence. This error is never reported for " { $link SSLv2 } " connections because there is no distinction between expected and unexpected connection closure in that case." } ;
|
||||||
|
|
||||||
|
HELP: certificate-verify-error
|
||||||
|
{ $error-description "Thrown if certificate verification failed. The " { $snippet "result" } " slot contains an object identifying the low-level error that occurred." } ;
|
||||||
|
|
||||||
|
HELP: common-name-verify-error
|
||||||
|
{ $error-description "Thrown during certificate verification if the host name on the certificate does not match the host name the socket was connected to. This indicates a potential man-in-the-middle attack. The " { $snippet "expected" } " and " { $snippet "got" } " slots contain the mismatched host names." } ;
|
||||||
|
|
||||||
|
ARTICLE: "ssl-errors" "Secure socket errors"
|
||||||
|
"Secure sockets can throw one of several errors in addition to the usual I/O errors:"
|
||||||
|
{ $subsection premature-close }
|
||||||
|
{ $subsection certificate-verify-error }
|
||||||
|
{ $subsection common-name-verify-error } ;
|
||||||
|
|
||||||
|
ARTICLE: "io.sockets.secure" "Secure sockets (SSL, TLS)"
|
||||||
|
"The " { $vocab-link "io.sockets.secure" } " vocabulary implements secure, encrypted sockets using the OpenSSL library."
|
||||||
|
{ $subsection "ssl-config" }
|
||||||
|
{ $subsection "ssl-contexts" }
|
||||||
|
{ $subsection "ssl-addresses" }
|
||||||
|
{ $subsection "ssl-errors" }
|
||||||
|
"This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (" { $url "http://www.openssl.org/" } "), cryptographic software written by Eric Young (eay@cryptsoft.com) and software written by Tim Hudson (tjh@cryptsoft.com)." ;
|
||||||
|
|
||||||
|
ABOUT: "io.sockets.secure"
|
|
@ -15,6 +15,8 @@ SINGLETONS: SSLv2 SSLv23 SSLv3 TLSv1 ;
|
||||||
TUPLE: secure-config
|
TUPLE: secure-config
|
||||||
method
|
method
|
||||||
key-file password
|
key-file password
|
||||||
|
verify
|
||||||
|
verify-depth
|
||||||
ca-file ca-path
|
ca-file ca-path
|
||||||
dh-file
|
dh-file
|
||||||
ephemeral-key-bits ;
|
ephemeral-key-bits ;
|
||||||
|
@ -22,7 +24,9 @@ ephemeral-key-bits ;
|
||||||
: <secure-config> ( -- config )
|
: <secure-config> ( -- config )
|
||||||
secure-config new
|
secure-config new
|
||||||
SSLv23 >>method
|
SSLv23 >>method
|
||||||
512 >>ephemeral-key-bits ;
|
1024 >>ephemeral-key-bits
|
||||||
|
"resource:extra/openssl/cacert.pem" >>ca-file
|
||||||
|
t >>verify ;
|
||||||
|
|
||||||
TUPLE: secure-context config handle disposed ;
|
TUPLE: secure-context config handle disposed ;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Secure sockets (SSL, TLS)
|
|
@ -0,0 +1 @@
|
||||||
|
network
|
|
@ -27,7 +27,8 @@ $nl
|
||||||
{ { $link inet4 } " - a TCP/IP connection to an IPv4 address and port number; no name lookup is performed" }
|
{ { $link inet4 } " - a TCP/IP connection to an IPv4 address and port number; no name lookup is performed" }
|
||||||
{ { $link inet6 } " - a TCP/IP connection to an IPv6 address and port number; no name lookup is performed" }
|
{ { $link inet6 } " - a TCP/IP connection to an IPv6 address and port number; no name lookup is performed" }
|
||||||
}
|
}
|
||||||
"The " { $vocab-link "io.server" } " library defines a nice high-level wrapper around " { $link <server> } " which makes it easy to listen for IPv4 and IPv6 connections simultaneously, perform logging, and optionally only allow connections from the loopback interface." ;
|
"The " { $vocab-link "io.server" } " library defines a nice high-level wrapper around " { $link <server> } " which makes it easy to listen for IPv4 and IPv6 connections simultaneously, perform logging, and optionally only allow connections from the loopback interface."
|
||||||
|
{ $see-also "io.sockets.secure" } ;
|
||||||
|
|
||||||
ARTICLE: "network-packet" "Packet-oriented networking"
|
ARTICLE: "network-packet" "Packet-oriented networking"
|
||||||
"A packet-oriented socket can be opened with this word:"
|
"A packet-oriented socket can be opened with this word:"
|
||||||
|
@ -49,11 +50,13 @@ ARTICLE: "network-streams" "Networking"
|
||||||
"Factor supports connection-oriented and packet-oriented communication over a variety of protocols:"
|
"Factor supports connection-oriented and packet-oriented communication over a variety of protocols:"
|
||||||
{ $list
|
{ $list
|
||||||
"TCP/IP and UDP/IP, over IPv4 and IPv6"
|
"TCP/IP and UDP/IP, over IPv4 and IPv6"
|
||||||
"Unix domain sockets"
|
"Unix domain sockets (Unix only)"
|
||||||
}
|
}
|
||||||
{ $subsection "network-addressing" }
|
{ $subsection "network-addressing" }
|
||||||
{ $subsection "network-connection" }
|
{ $subsection "network-connection" }
|
||||||
{ $subsection "network-packet" } ;
|
{ $subsection "network-packet" }
|
||||||
|
{ $subsection "io.sockets.secure" }
|
||||||
|
{ $see-also "io.pipes" } ;
|
||||||
|
|
||||||
ABOUT: "network-streams"
|
ABOUT: "network-streams"
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,13 @@ TUPLE: fd fd disposed ;
|
||||||
[ >>fd ]
|
[ >>fd ]
|
||||||
tri ;
|
tri ;
|
||||||
|
|
||||||
M: fd dispose*
|
M: fd dispose
|
||||||
[ cancel-operation ] [ fd>> close-file ] bi ;
|
dup disposed>> [ drop ] [
|
||||||
|
[ cancel-operation ]
|
||||||
|
[ t >>disposed drop ]
|
||||||
|
[ fd>> close-file ]
|
||||||
|
tri
|
||||||
|
] if ;
|
||||||
|
|
||||||
M: fd handle-fd dup check-disposed fd>> ;
|
M: fd handle-fd dup check-disposed fd>> ;
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ concurrency.promises byte-arrays locals calendar io.timeouts ;
|
||||||
: with-test-context
|
: with-test-context
|
||||||
<secure-config>
|
<secure-config>
|
||||||
"resource:extra/openssl/test/server.pem" >>key-file
|
"resource:extra/openssl/test/server.pem" >>key-file
|
||||||
"resource:extra/openssl/test/root.pem" >>ca-file
|
|
||||||
"resource:extra/openssl/test/dh1024.pem" >>dh-file
|
"resource:extra/openssl/test/dh1024.pem" >>dh-file
|
||||||
"password" >>password
|
"password" >>password
|
||||||
swap with-secure-context ;
|
swap with-secure-context ;
|
||||||
|
@ -44,8 +43,8 @@ concurrency.promises byte-arrays locals calendar io.timeouts ;
|
||||||
[ ] [
|
[ ] [
|
||||||
[
|
[
|
||||||
drop
|
drop
|
||||||
input-stream get stream>> handle>> f >>connected drop
|
|
||||||
"hello" write flush
|
"hello" write flush
|
||||||
|
input-stream get stream>> handle>> f >>connected drop
|
||||||
] server-test
|
] server-test
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
@ -55,7 +54,7 @@ concurrency.promises byte-arrays locals calendar io.timeouts ;
|
||||||
! actually an invalid certificate
|
! actually an invalid certificate
|
||||||
[ ] [ <promise> "port" set ] unit-test
|
[ ] [ <promise> "port" set ] unit-test
|
||||||
|
|
||||||
[ ] [ [ drop ] server-test ] unit-test
|
[ ] [ [ drop "hi" write ] server-test ] unit-test
|
||||||
|
|
||||||
[
|
[
|
||||||
<secure-config> [
|
<secure-config> [
|
||||||
|
@ -97,13 +96,16 @@ concurrency.promises byte-arrays locals calendar io.timeouts ;
|
||||||
[
|
[
|
||||||
"127.0.0.1" 0 <inet4> <secure> ascii <server> [
|
"127.0.0.1" 0 <inet4> <secure> ascii <server> [
|
||||||
dup addr>> addrspec>> port>> "port" get fulfill
|
dup addr>> addrspec>> port>> "port" get fulfill
|
||||||
accept drop dispose
|
accept drop dup stream-read1 drop dispose
|
||||||
] with-disposal
|
] with-disposal
|
||||||
] with-test-context
|
] with-test-context
|
||||||
] with-variable
|
] with-variable
|
||||||
] [ io-timeout? ] must-fail-with
|
] [ io-timeout? ] must-fail-with
|
||||||
|
|
||||||
! Client socket shutdown timeout
|
! Client socket shutdown timeout
|
||||||
|
|
||||||
|
! Until I sort out two-stage handshaking, I can't do much here
|
||||||
|
[
|
||||||
[ ] [ <promise> "port" set ] unit-test
|
[ ] [ <promise> "port" set ] unit-test
|
||||||
|
|
||||||
[ ] [
|
[ ] [
|
||||||
|
@ -148,3 +150,4 @@ concurrency.promises byte-arrays locals calendar io.timeouts ;
|
||||||
] with-test-context
|
] with-test-context
|
||||||
] with-variable
|
] with-variable
|
||||||
] [ io-timeout? ] must-fail-with
|
] [ io-timeout? ] must-fail-with
|
||||||
|
] drop
|
||||||
|
|
|
@ -22,6 +22,26 @@ M: ssl-handle handle-fd file>> handle-fd ;
|
||||||
nip (ssl-error)
|
nip (ssl-error)
|
||||||
] if ;
|
] if ;
|
||||||
|
|
||||||
|
: check-accept-response ( handle r -- event )
|
||||||
|
over handle>> over SSL_get_error
|
||||||
|
{
|
||||||
|
{ SSL_ERROR_NONE [ 2drop f ] }
|
||||||
|
{ SSL_ERROR_WANT_READ [ 2drop +input+ ] }
|
||||||
|
{ SSL_ERROR_WANT_WRITE [ 2drop +output+ ] }
|
||||||
|
{ SSL_ERROR_SYSCALL [ syscall-error ] }
|
||||||
|
{ SSL_ERROR_SSL [ (ssl-error) ] }
|
||||||
|
} case ;
|
||||||
|
|
||||||
|
: do-ssl-accept ( ssl-handle -- )
|
||||||
|
dup dup handle>> SSL_accept check-accept-response dup
|
||||||
|
[ >r dup file>> r> wait-for-fd do-ssl-accept ] [ 2drop ] if ;
|
||||||
|
|
||||||
|
: maybe-handshake ( ssl-handle -- )
|
||||||
|
dup connected>> [ drop ] [
|
||||||
|
t >>connected
|
||||||
|
[ do-ssl-accept ] with-timeout
|
||||||
|
] if ;
|
||||||
|
|
||||||
: check-response ( port r -- port r n )
|
: check-response ( port r -- port r n )
|
||||||
over handle>> handle>> over SSL_get_error ; inline
|
over handle>> handle>> over SSL_get_error ; inline
|
||||||
|
|
||||||
|
@ -38,6 +58,7 @@ M: ssl-handle handle-fd file>> handle-fd ;
|
||||||
} case ;
|
} case ;
|
||||||
|
|
||||||
M: ssl-handle refill
|
M: ssl-handle refill
|
||||||
|
dup maybe-handshake
|
||||||
handle>> ! ssl
|
handle>> ! ssl
|
||||||
over buffer>>
|
over buffer>>
|
||||||
[ buffer-end ] ! buf
|
[ buffer-end ] ! buf
|
||||||
|
@ -57,6 +78,7 @@ M: ssl-handle refill
|
||||||
} case ;
|
} case ;
|
||||||
|
|
||||||
M: ssl-handle drain
|
M: ssl-handle drain
|
||||||
|
dup maybe-handshake
|
||||||
handle>> ! ssl
|
handle>> ! ssl
|
||||||
over buffer>>
|
over buffer>>
|
||||||
[ buffer@ ] ! buf
|
[ buffer@ ] ! buf
|
||||||
|
@ -107,52 +129,25 @@ M: secure establish-connection ( client-out remote -- )
|
||||||
|
|
||||||
M: secure (server) addrspec>> (server) ;
|
M: secure (server) addrspec>> (server) ;
|
||||||
|
|
||||||
: check-accept-response ( handle r -- event )
|
M: secure (accept)
|
||||||
|
[
|
||||||
|
addrspec>> (accept) >r |dispose <ssl-socket> r>
|
||||||
|
] with-destructors ;
|
||||||
|
|
||||||
|
: check-shutdown-response ( handle r -- event )
|
||||||
|
#! We don't do two-step shutdown here because I couldn't
|
||||||
|
#! figure out how to do it with non-blocking BIOs. Also, it
|
||||||
|
#! seems that SSL_shutdown always returns 0 -- this sounds
|
||||||
|
#! like a bug
|
||||||
over handle>> over SSL_get_error
|
over handle>> over SSL_get_error
|
||||||
{
|
{
|
||||||
{ SSL_ERROR_NONE [ 2drop f ] }
|
{ SSL_ERROR_NONE [ 2drop f ] }
|
||||||
{ SSL_ERROR_WANT_READ [ 2drop +input+ ] }
|
{ SSL_ERROR_WANT_READ [ 2drop +input+ ] }
|
||||||
{ SSL_ERROR_WANT_WRITE [ 2drop +output+ ] }
|
{ SSL_ERROR_WANT_WRITE [ 2drop +output+ ] }
|
||||||
{ SSL_ERROR_SYSCALL [ syscall-error ] }
|
{ SSL_ERROR_SYSCALL [ dup zero? [ 2drop f ] [ syscall-error ] if ] }
|
||||||
{ SSL_ERROR_SSL [ (ssl-error) ] }
|
{ SSL_ERROR_SSL [ (ssl-error) ] }
|
||||||
} case ;
|
} case ;
|
||||||
|
|
||||||
: do-ssl-accept ( ssl-handle -- )
|
|
||||||
dup dup handle>> SSL_accept check-accept-response dup
|
|
||||||
[ >r dup file>> r> wait-for-fd do-ssl-accept ] [ 2drop ] if ;
|
|
||||||
|
|
||||||
M: secure (accept)
|
|
||||||
[
|
|
||||||
addrspec>> (accept) >r
|
|
||||||
|dispose <ssl-socket> t >>connected |dispose
|
|
||||||
dup [ do-ssl-accept ] with-timeout r>
|
|
||||||
] with-destructors ;
|
|
||||||
|
|
||||||
: check-shutdown-response ( handle r -- event )
|
|
||||||
#! SSL_shutdown always returns 0 due to openssl bugs?
|
|
||||||
{
|
|
||||||
{ 1 [ drop f ] }
|
|
||||||
{ 0 [
|
|
||||||
dup handle>> dup f 0 SSL_read 2dup SSL_get_error
|
|
||||||
{
|
|
||||||
{ SSL_ERROR_ZERO_RETURN [ 3drop +retry+ ] }
|
|
||||||
{ SSL_ERROR_WANT_READ [ 3drop +input+ ] }
|
|
||||||
{ SSL_ERROR_WANT_WRITE [ 3drop +output+ ] }
|
|
||||||
{ SSL_ERROR_SYSCALL [ syscall-error ] }
|
|
||||||
{ SSL_ERROR_SSL [ (ssl-error) ] }
|
|
||||||
} case
|
|
||||||
] }
|
|
||||||
{ -1 [
|
|
||||||
handle>> -1 SSL_get_error
|
|
||||||
{
|
|
||||||
{ SSL_ERROR_WANT_READ [ +input+ ] }
|
|
||||||
{ SSL_ERROR_WANT_WRITE [ +output+ ] }
|
|
||||||
{ SSL_ERROR_SYSCALL [ -1 syscall-error ] }
|
|
||||||
{ SSL_ERROR_SSL [ (ssl-error) ] }
|
|
||||||
} case
|
|
||||||
] }
|
|
||||||
} case ;
|
|
||||||
|
|
||||||
: (shutdown) ( handle -- )
|
: (shutdown) ( handle -- )
|
||||||
dup dup handle>> SSL_shutdown check-shutdown-response
|
dup dup handle>> SSL_shutdown check-shutdown-response
|
||||||
dup [ dupd wait-for-fd (shutdown) ] [ 2drop ] if ;
|
dup [ dupd wait-for-fd (shutdown) ] [ 2drop ] if ;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: alien alien.c-types arrays destructors io io.backend
|
USING: alien alien.c-types arrays destructors io io.backend
|
||||||
io.buffers io.files io.ports io.sockets io.binary
|
io.buffers io.files io.ports io.sockets io.binary
|
||||||
io.sockets windows.errors strings
|
io.sockets io.timeouts windows.errors strings
|
||||||
kernel math namespaces sequences windows windows.kernel32
|
kernel math namespaces sequences windows windows.kernel32
|
||||||
windows.shell32 windows.types windows.winsock splitting
|
windows.shell32 windows.types windows.winsock splitting
|
||||||
continuations math.bitfields system accessors ;
|
continuations math.bitfields system accessors ;
|
||||||
|
@ -24,8 +24,10 @@ TUPLE: win32-file < win32-handle ptr ;
|
||||||
: <win32-file> ( handle -- win32-file )
|
: <win32-file> ( handle -- win32-file )
|
||||||
win32-file new-win32-handle ;
|
win32-file new-win32-handle ;
|
||||||
|
|
||||||
M: win32-file dispose*
|
M: win32-file dispose
|
||||||
[ cancel-operation ] [ call-next-method ] bi ;
|
dup disposed>> [ drop ] [
|
||||||
|
[ cancel-operation ] [ call-next-method ] bi
|
||||||
|
] if ;
|
||||||
|
|
||||||
HOOK: CreateFile-flags io-backend ( DWORD -- DWORD )
|
HOOK: CreateFile-flags io-backend ( DWORD -- DWORD )
|
||||||
HOOK: FileArgs-overlapped io-backend ( port -- overlapped/f )
|
HOOK: FileArgs-overlapped io-backend ( port -- overlapped/f )
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -122,6 +122,11 @@ FUNCTION: int SSL_read ( ssl-pointer ssl, void* buf, int num ) ;
|
||||||
|
|
||||||
FUNCTION: int SSL_shutdown ( ssl-pointer ssl ) ;
|
FUNCTION: int SSL_shutdown ( ssl-pointer ssl ) ;
|
||||||
|
|
||||||
|
: SSL_SENT_SHUTDOWN 1 ;
|
||||||
|
: SSL_RECEIVED_SHUTDOWN 2 ;
|
||||||
|
|
||||||
|
FUNCTION: int SSL_get_shutdown ( ssl-pointer ssl ) ;
|
||||||
|
|
||||||
FUNCTION: void SSL_free ( ssl-pointer ssl ) ;
|
FUNCTION: void SSL_free ( ssl-pointer ssl ) ;
|
||||||
|
|
||||||
FUNCTION: int SSL_want ( ssl-pointer ssl ) ;
|
FUNCTION: int SSL_want ( ssl-pointer ssl ) ;
|
||||||
|
@ -151,6 +156,15 @@ FUNCTION: int SSL_use_certificate_file ( ssl-pointer ssl,
|
||||||
FUNCTION: int SSL_CTX_load_verify_locations ( ssl-ctx ctx, char* CAfile,
|
FUNCTION: int SSL_CTX_load_verify_locations ( ssl-ctx ctx, char* CAfile,
|
||||||
char* CApath ) ;
|
char* CApath ) ;
|
||||||
|
|
||||||
|
FUNCTION: int SSL_CTX_set_default_verify_paths ( ssl-ctx ctx ) ;
|
||||||
|
|
||||||
|
: SSL_VERIFY_NONE 0 ; inline
|
||||||
|
: SSL_VERIFY_PEER 1 ; inline
|
||||||
|
: SSL_VERIFY_FAIL_IF_NO_PEER_CERT 2 ; inline
|
||||||
|
: SSL_VERIFY_CLIENT_ONCE 4 ; inline
|
||||||
|
|
||||||
|
FUNCTION: void SSL_CTX_set_verify ( ssl-ctx ctx, int mode, void* callback ) ;
|
||||||
|
|
||||||
FUNCTION: void SSL_CTX_set_client_CA_list ( ssl-ctx ctx, ssl-pointer list ) ;
|
FUNCTION: void SSL_CTX_set_client_CA_list ( ssl-ctx ctx, ssl-pointer list ) ;
|
||||||
|
|
||||||
FUNCTION: ssl-pointer SSL_load_client_CA_file ( char* file ) ;
|
FUNCTION: ssl-pointer SSL_load_client_CA_file ( char* file ) ;
|
||||||
|
|
|
@ -94,11 +94,14 @@ TUPLE: openssl-context < secure-context aliens ;
|
||||||
[ ca-file>> dup [ (normalize-path) ] when ]
|
[ ca-file>> dup [ (normalize-path) ] when ]
|
||||||
[ ca-path>> dup [ (normalize-path) ] when ] bi
|
[ ca-path>> dup [ (normalize-path) ] when ] bi
|
||||||
] bi
|
] bi
|
||||||
SSL_CTX_load_verify_locations ssl-error
|
SSL_CTX_load_verify_locations
|
||||||
] [ drop ] if ;
|
] [ handle>> SSL_CTX_set_default_verify_paths ] if ssl-error ;
|
||||||
|
|
||||||
: set-verify-depth ( ctx -- )
|
: set-verify-depth ( ctx -- )
|
||||||
handle>> 1 SSL_CTX_set_verify_depth ;
|
dup config>> verify-depth>> [
|
||||||
|
[ handle>> ] [ config>> verify-depth>> ] bi
|
||||||
|
SSL_CTX_set_verify_depth
|
||||||
|
] [ drop ] if ;
|
||||||
|
|
||||||
TUPLE: bio handle disposed ;
|
TUPLE: bio handle disposed ;
|
||||||
|
|
||||||
|
@ -154,11 +157,6 @@ M: openssl-context dispose*
|
||||||
|
|
||||||
TUPLE: ssl-handle file handle connected disposed ;
|
TUPLE: ssl-handle file handle connected disposed ;
|
||||||
|
|
||||||
ERROR: no-secure-context ;
|
|
||||||
|
|
||||||
M: no-secure-context summary
|
|
||||||
drop "Secure socket operations must be wrapped in calls to with-secure-context" ;
|
|
||||||
|
|
||||||
SYMBOL: default-secure-context
|
SYMBOL: default-secure-context
|
||||||
|
|
||||||
: context-expired? ( context -- ? )
|
: context-expired? ( context -- ? )
|
||||||
|
@ -195,9 +193,11 @@ M: ssl-handle dispose*
|
||||||
[ 2drop ] [ common-name-verify-error ] if ;
|
[ 2drop ] [ common-name-verify-error ] if ;
|
||||||
|
|
||||||
M: openssl check-certificate ( host ssl -- )
|
M: openssl check-certificate ( host ssl -- )
|
||||||
|
current-secure-context config>> verify>> [
|
||||||
handle>>
|
handle>>
|
||||||
[ nip check-verify-result ]
|
[ nip check-verify-result ]
|
||||||
[ check-common-name ]
|
[ check-common-name ]
|
||||||
2bi ;
|
2bi
|
||||||
|
] [ 2drop ] if ;
|
||||||
|
|
||||||
openssl secure-socket-backend set-global
|
openssl secure-socket-backend set-global
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
enterprise
|
|
||||||
network
|
network
|
||||||
bindings
|
bindings
|
||||||
|
|
|
@ -131,6 +131,116 @@ IN: regexp4-tests
|
||||||
[ f ] [ "\\" "[^\\\\]" <regexp> matches? ] unit-test
|
[ f ] [ "\\" "[^\\\\]" <regexp> matches? ] unit-test
|
||||||
[ t ] [ "a" "[^\\\\]" <regexp> matches? ] unit-test
|
[ t ] [ "a" "[^\\\\]" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ "0" "[\\d]" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "a" "[\\d]" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "0" "[^\\d]" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "a" "[^\\d]" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ "a" "[a-z]{1,}|[A-Z]{2,4}|b*|c|(f|g)*" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "a" "[a-z]{1,2}|[A-Z]{3,3}|b*|c|(f|g)*" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "a" "[a-z]{1,2}|[A-Z]{3,3}" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ "1000" "\\d{4,6}" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "1000" "[0-9]{4,6}" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ "abc" "\\p{Lower}{3}" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "ABC" "\\p{Lower}{3}" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "ABC" "\\p{Upper}{3}" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "abc" "\\p{Upper}{3}" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
[ f ] [ "abc" "[\\p{Upper}]{3}" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "ABC" "[\\p{Upper}]{3}" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ "" "\\Q\\E" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "a" "\\Q\\E" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "|*+" "\\Q|*+\\E" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "abc" "\\Q|*+\\E" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ "S" "\\0123" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "SXY" "\\0123XY" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "x" "\\x78" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "y" "\\x78" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "x" "\\u000078" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "y" "\\u000078" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ "ab" "a+b" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "b" "a+b" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "aab" "a+b" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "abb" "a+b" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ "abbbb" "ab*" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "a" "ab*" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "abab" "ab*" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
[ f ] [ "x" "\\." <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "." "\\." <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ "aaaab" "a+ab" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "aaaxb" "a+ab" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "aaacb" "a+cb" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "aaaab" "a++ab" <regexp> matches? ] unit-test
|
||||||
|
[ t ] [ "aaacb" "a++cb" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
[ 3 ] [ "aaacb" "a*" <regexp> match-head ] unit-test
|
||||||
|
[ 1 ] [ "aaacb" "a+?" <regexp> match-head ] unit-test
|
||||||
|
[ 2 ] [ "aaacb" "aa?" <regexp> match-head ] unit-test
|
||||||
|
[ 1 ] [ "aaacb" "aa??" <regexp> match-head ] unit-test
|
||||||
|
[ 3 ] [ "aacb" "aa?c" <regexp> match-head ] unit-test
|
||||||
|
[ 3 ] [ "aacb" "aa??c" <regexp> match-head ] unit-test
|
||||||
|
|
||||||
|
! [ t ] [ "aaa" "AAA" t <regexp> matches? ] unit-test
|
||||||
|
! [ f ] [ "aax" "AAA" t <regexp> matches? ] unit-test
|
||||||
|
! [ t ] [ "aaa" "A*" t <regexp> matches? ] unit-test
|
||||||
|
! [ f ] [ "aaba" "A*" t <regexp> matches? ] unit-test
|
||||||
|
! [ t ] [ "b" "[AB]" t <regexp> matches? ] unit-test
|
||||||
|
! [ f ] [ "c" "[AB]" t <regexp> matches? ] unit-test
|
||||||
|
! [ t ] [ "c" "[A-Z]" t <regexp> matches? ] unit-test
|
||||||
|
! [ f ] [ "3" "[A-Z]" t <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
[ ] [
|
||||||
|
"(0[lL]?|[1-9]\\d{0,9}(\\d{0,9}[lL])?|0[xX]\\p{XDigit}{1,8}(\\p{XDigit}{0,8}[lL])?|0[0-7]{1,11}([0-7]{0,11}[lL])?|([0-9]+\\.[0-9]*|\\.[0-9]+)([eE][+-]?[0-9]+)?[fFdD]?|[0-9]+([eE][+-]?[0-9]+[fFdD]?|([eE][+-]?[0-9]+)?[fFdD]))"
|
||||||
|
<regexp> drop
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ t ] [ "fxxbar" "(?!foo).{3}bar" <regexp> matches? ] unit-test
|
||||||
|
[ f ] [ "foobar" "(?!foo).{3}bar" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
! [ 3 ] [ "foobar" "foo(?=bar)" <regexp> match-head ] unit-test
|
||||||
|
! [ f ] [ "foobxr" "foo(?=bar)" <regexp> match-head ] unit-test
|
||||||
|
|
||||||
|
! [ f ] [ "foobxr" "foo\\z" <regexp> match-head ] unit-test
|
||||||
|
! [ 3 ] [ "foo" "foo\\z" <regexp> match-head ] unit-test
|
||||||
|
|
||||||
|
! [ 3 ] [ "foo bar" "foo\\b" <regexp> match-head ] unit-test
|
||||||
|
! [ f ] [ "fooxbar" "foo\\b" <regexp> matches? ] unit-test
|
||||||
|
! [ t ] [ "foo" "foo\\b" <regexp> matches? ] unit-test
|
||||||
|
! [ t ] [ "foo bar" "foo\\b bar" <regexp> matches? ] unit-test
|
||||||
|
! [ f ] [ "fooxbar" "foo\\bxbar" <regexp> matches? ] unit-test
|
||||||
|
! [ f ] [ "foo" "foo\\bbar" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
! [ f ] [ "foo bar" "foo\\B" <regexp> matches? ] unit-test
|
||||||
|
! [ 3 ] [ "fooxbar" "foo\\B" <regexp> match-head ] unit-test
|
||||||
|
! [ t ] [ "foo" "foo\\B" <regexp> matches? ] unit-test
|
||||||
|
! [ f ] [ "foo bar" "foo\\B bar" <regexp> matches? ] unit-test
|
||||||
|
! [ t ] [ "fooxbar" "foo\\Bxbar" <regexp> matches? ] unit-test
|
||||||
|
! [ f ] [ "foo" "foo\\Bbar" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
! [ t ] [ "s@f" "[a-z.-]@[a-z]" <regexp> matches? ] unit-test
|
||||||
|
! [ f ] [ "a" "[a-z.-]@[a-z]" <regexp> matches? ] unit-test
|
||||||
|
! [ t ] [ ".o" "\\.[a-z]" <regexp> matches? ] unit-test
|
||||||
|
|
||||||
|
! Bug in parsing word
|
||||||
|
[ t ] [
|
||||||
|
"a"
|
||||||
|
R' a'
|
||||||
|
matches?
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
! ((A)(B(C)))
|
! ((A)(B(C)))
|
||||||
! 1. ((A)(B(C)))
|
! 1. ((A)(B(C)))
|
||||||
|
|
|
@ -4,7 +4,7 @@ USING: accessors arrays assocs combinators kernel math
|
||||||
sequences namespaces locals combinators.lib state-tables
|
sequences namespaces locals combinators.lib state-tables
|
||||||
math.parser state-parser sets dlists unicode.categories
|
math.parser state-parser sets dlists unicode.categories
|
||||||
math.order quotations shuffle math.ranges splitting
|
math.order quotations shuffle math.ranges splitting
|
||||||
symbols fry ;
|
symbols fry parser ;
|
||||||
IN: regexp4
|
IN: regexp4
|
||||||
|
|
||||||
SYMBOLS: eps start-state final-state beginning-of-text
|
SYMBOLS: eps start-state final-state beginning-of-text
|
||||||
|
@ -544,6 +544,33 @@ ERROR: unsupported-token token ;
|
||||||
<vector-table> >>nfa
|
<vector-table> >>nfa
|
||||||
dup [ parse-raw-regexp ] [ subset-construction ] bi ;
|
dup [ parse-raw-regexp ] [ subset-construction ] bi ;
|
||||||
|
|
||||||
|
! Literal syntax for regexps
|
||||||
|
: parse-options ( string -- ? )
|
||||||
|
#! Lame
|
||||||
|
{
|
||||||
|
{ "" [ f ] }
|
||||||
|
{ "i" [ t ] }
|
||||||
|
} case ;
|
||||||
|
|
||||||
|
: parse-regexp ( accum end -- accum )
|
||||||
|
lexer get dup skip-blank
|
||||||
|
[ [ index-from dup 1+ swap ] 2keep swapd subseq swap ] change-lexer-column
|
||||||
|
! lexer get dup still-parsing-line?
|
||||||
|
! [ (parse-token) parse-options ] [ drop f ] if
|
||||||
|
<regexp> parsed ;
|
||||||
|
|
||||||
|
: R! CHAR: ! parse-regexp ; parsing
|
||||||
|
: R" CHAR: " parse-regexp ; parsing
|
||||||
|
: R# CHAR: # parse-regexp ; parsing
|
||||||
|
: R' CHAR: ' parse-regexp ; parsing
|
||||||
|
: R( CHAR: ) parse-regexp ; parsing
|
||||||
|
: R/ CHAR: / parse-regexp ; parsing
|
||||||
|
: R@ CHAR: @ parse-regexp ; parsing
|
||||||
|
: R[ CHAR: ] parse-regexp ; parsing
|
||||||
|
: R` CHAR: ` parse-regexp ; parsing
|
||||||
|
: R{ CHAR: } parse-regexp ; parsing
|
||||||
|
: R| CHAR: | parse-regexp ; parsing
|
||||||
|
|
||||||
TUPLE: dfa-traverser
|
TUPLE: dfa-traverser
|
||||||
dfa
|
dfa
|
||||||
last-state current-state
|
last-state current-state
|
||||||
|
@ -611,6 +638,9 @@ TUPLE: dfa-traverser
|
||||||
: matches? ( string regexp -- ? )
|
: matches? ( string regexp -- ? )
|
||||||
dupd match [ [ length ] [ range-length 1- ] bi* = ] [ drop f ] if* ;
|
dupd match [ [ length ] [ range-length 1- ] bi* = ] [ drop f ] if* ;
|
||||||
|
|
||||||
|
: match-head ( string regexp -- end )
|
||||||
|
match length>> ;
|
||||||
|
|
||||||
! character classes
|
! character classes
|
||||||
! TUPLE: range-class from to ;
|
! TUPLE: range-class from to ;
|
||||||
! TUPLE: or-class left right ;
|
! TUPLE: or-class left right ;
|
||||||
|
|
|
@ -160,6 +160,7 @@ M: stack-display tool-scroller
|
||||||
{
|
{
|
||||||
[ com-end ]
|
[ com-end ]
|
||||||
[ clear-output ]
|
[ clear-output ]
|
||||||
|
[ input>> clear-input ]
|
||||||
[ start-listener-thread ]
|
[ start-listener-thread ]
|
||||||
[ wait-for-listener ]
|
[ wait-for-listener ]
|
||||||
} cleave ;
|
} cleave ;
|
||||||
|
|
|
@ -2,4 +2,4 @@ include vm/Config.unix
|
||||||
PLAF_DLL_OBJS += vm/os-genunix.o vm/os-netbsd.o
|
PLAF_DLL_OBJS += vm/os-genunix.o vm/os-netbsd.o
|
||||||
CFLAGS += -export-dynamic
|
CFLAGS += -export-dynamic
|
||||||
LIBPATH = -L/usr/X11R6/lib -Wl,-rpath,/usr/X11R6/lib -L/usr/pkg/lib -Wl,-rpath,/usr/pkg/lib
|
LIBPATH = -L/usr/X11R6/lib -Wl,-rpath,/usr/X11R6/lib -L/usr/pkg/lib -Wl,-rpath,/usr/pkg/lib
|
||||||
LIBS = -lm $(X11_UI_LIBS)
|
LIBS = -lm -lopenal -lalut $(X11_UI_LIBS)
|
||||||
|
|
Loading…
Reference in New Issue