diff options
author | Konstantin Molchanov <moigagoo@live.com> | 2017-03-29 16:54:36 +0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-29 16:54:36 +0400 |
commit | 04646052aba3e52d962eb20388588ff6be92bda8 (patch) | |
tree | f9d3387bb2d5f9b9dcc0de33527c1f69b9e4527e /lib | |
parent | 0c121b38eccde230255d706131c46434e29018e1 (diff) | |
parent | 875e344be0f0202885f0d5ed7f10188835a171d0 (diff) | |
download | Nim-04646052aba3e52d962eb20388588ff6be92bda8.tar.gz |
Merge branch 'devel' into fix_time_offset_in_times_js
Diffstat (limited to 'lib')
-rw-r--r-- | lib/js/dom.nim | 30 | ||||
-rw-r--r-- | lib/posix/posix.nim | 9 | ||||
-rw-r--r-- | lib/pure/asynchttpserver.nim | 34 | ||||
-rw-r--r-- | lib/pure/asyncmacro.nim | 27 | ||||
-rw-r--r-- | lib/pure/asyncnet.nim | 16 | ||||
-rw-r--r-- | lib/pure/concurrency/threadpool.nim | 2 | ||||
-rw-r--r-- | lib/pure/httpcore.nim | 4 | ||||
-rw-r--r-- | lib/pure/net.nim | 11 |
8 files changed, 91 insertions, 42 deletions
diff --git a/lib/js/dom.nim b/lib/js/dom.nim index 5a33dfa9f..a879ddb61 100644 --- a/lib/js/dom.nim +++ b/lib/js/dom.nim @@ -130,6 +130,16 @@ type readOnly*: bool options*: seq[OptionElement] + # https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement + HtmlElement* = ref object of Element + contentEditable*: string + isContentEditable*: bool + dir*: string + offsetHeight*: int + offsetWidth*: int + offsetLeft*: int + offsetTop*: int + LinkElement* = ref LinkObj LinkObj {.importc.} = object of ElementObj target*: cstring @@ -270,6 +280,8 @@ type wordSpacing*: cstring zIndex*: int + # TODO: A lot of the fields in Event belong to a more specific type of event. + # TODO: Should we clean this up? Event* = ref EventObj EventObj {.importc.} = object of RootObj target*: Node @@ -310,6 +322,20 @@ type SUBMIT*: int UNLOAD*: int + TouchList* {.importc.} = ref object of RootObj + length*: int + + TouchEvent* {.importc.} = ref object of Event + changedTouches*, targetTouches*, touches*: TouchList + + Touch* {.importc.} = ref object of RootObj + identifier*: int + screenX*, screenY*, clientX*, clientY*, pageX*, pageY*: int + target*: Element + radiusX*, radiusY*: int + rotationAngle*: int + force*: float + Location* = ref LocationObj LocationObj {.importc.} = object of RootObj hash*: cstring @@ -488,6 +514,10 @@ proc setAttribute*(s: Style, attr, value: cstring, caseSensitive=false) # Event "methods" proc preventDefault*(ev: Event) +# TouchEvent "methods" +proc identifiedTouch*(list: TouchList): Touch +proc item*(list: TouchList, i: int): Touch + {.pop.} var diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index a18db2150..b29f43eb4 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -109,12 +109,17 @@ type Dirent* {.importc: "struct dirent", header: "<dirent.h>", final, pure.} = object ## dirent_t struct d_ino*: Ino ## File serial number. - when defined(linux) or defined(macosx) or defined(bsd): + when defined(dragonfly): + # DragonflyBSD doesn't have `d_reclen` field. + d_type*: uint8 + elif defined(linux) or defined(macosx) or defined(freebsd) or + defined(netbsd) or defined(openbsd): d_reclen*: cshort ## Length of this record. (not POSIX) d_type*: int8 ## Type of file; not supported by all filesystem types. ## (not POSIX) - when defined(linux) or defined(bsd): + when defined(linux) or defined(openbsd): d_off*: Off ## Not an offset. Value that ``telldir()`` would return. + d_name*: array[0..255, char] ## Name of entry. Tflock* {.importc: "struct flock", final, pure, diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index 80aa8bb2c..8d059dbbc 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -36,6 +36,9 @@ import httpcore export httpcore except parseHeader +const + maxLine = 8*1024 + # TODO: If it turns out that the decisions that asynchttpserver makes # explicitly, about whether to close the client sockets or upgrade them are # wrong, then add a return value which determines what to do for the callback. @@ -97,6 +100,18 @@ proc respond*(req: Request, code: HttpCode, content: string, if headers != nil: msg.addHeaders(headers) + msg.add("Content-Length: ") + # this particular way saves allocations: + msg.add content.len + msg.add "\c\L\c\L" + msg.add(content) + result = req.client.send(msg) + +proc respondError(req: Request, code: HttpCode): Future[void] = + ## Responds to the request with the specified ``HttpCode``. + let content = $code + var msg = "HTTP/1.1 " & content & "\c\L" + msg.add("Content-Length: " & $content.len & "\c\L\c\L") msg.add(content) result = req.client.send(msg) @@ -139,12 +154,16 @@ proc processClient(client: AsyncSocket, address: string, for i in 0..1: lineFut.mget().setLen(0) lineFut.clean() - await client.recvLineInto(lineFut) # TODO: Timeouts. + await client.recvLineInto(lineFut, maxLength=maxLine) # TODO: Timeouts. if lineFut.mget == "": client.close() return + if lineFut.mget.len > maxLine: + await request.respondError(Http413) + client.close() + return if lineFut.mget != "\c\L": break @@ -157,19 +176,17 @@ proc processClient(client: AsyncSocket, address: string, # TODO: this is likely slow. request.reqMethod = parseEnum[HttpMethod]("http" & linePart) except ValueError: - asyncCheck request.respond(Http400, "Invalid request method. Got: " & - linePart) + asyncCheck request.respondError(Http400) continue of 1: parseUri(linePart, request.url) of 2: try: request.protocol = parseProtocol(linePart) except ValueError: - asyncCheck request.respond(Http400, - "Invalid request protocol. Got: " & linePart) + asyncCheck request.respondError(Http400) continue else: - await request.respond(Http400, "Invalid request. Got: " & lineFut.mget) + await request.respondError(Http400) continue inc i @@ -178,10 +195,13 @@ proc processClient(client: AsyncSocket, address: string, i = 0 lineFut.mget.setLen(0) lineFut.clean() - await client.recvLineInto(lineFut) + await client.recvLineInto(lineFut, maxLength=maxLine) if lineFut.mget == "": client.close(); return + if lineFut.mget.len > maxLine: + await request.respondError(Http413) + client.close(); return if lineFut.mget == "\c\L": break let (key, value) = parseHeader(lineFut.mget) request.headers[key] = value diff --git a/lib/pure/asyncmacro.nim b/lib/pure/asyncmacro.nim index f0837d67d..ce4c9a9c9 100644 --- a/lib/pure/asyncmacro.nim +++ b/lib/pure/asyncmacro.nim @@ -40,6 +40,8 @@ template createCb(retFutureSym, iteratorNameSym, else: next.callback = cb except: + futureVarCompletions + if retFutureSym.finished: # Take a look at tasyncexceptions for the bug which this fixes. # That test explains it better than I can here. @@ -47,7 +49,6 @@ template createCb(retFutureSym, iteratorNameSym, else: retFutureSym.fail(getCurrentException()) - futureVarCompletions cb() #{.pop.} proc generateExceptionCheck(futSym, @@ -123,12 +124,16 @@ template createVar(result: var NimNode, futSymName: string, result.add newVarStmt(futSym, asyncProc) # -> var future<x> = y useVar(result, futSym, valueReceiver, rootReceiver, fromNode) -proc createFutureVarCompletions(futureVarIdents: seq[NimNode]): NimNode - {.compileTime.} = - result = newStmtList() +proc createFutureVarCompletions(futureVarIdents: seq[NimNode], + fromNode: NimNode): NimNode {.compileTime.} = + result = newNimNode(nnkStmtList, fromNode) # Add calls to complete each FutureVar parameter. for ident in futureVarIdents: # Only complete them if they have not been completed already by the user. + # TODO: Once https://github.com/nim-lang/Nim/issues/5617 is fixed. + # TODO: Add line info to the complete() call! + # In the meantime, this was really useful for debugging :) + #result.add(newCall(newIdentNode("echo"), newStrLitNode(fromNode.lineinfo))) result.add newIfStmt( ( newCall(newIdentNode("not"), @@ -145,6 +150,10 @@ proc processBody(node, retFutureSym: NimNode, case node.kind of nnkReturnStmt: result = newNimNode(nnkStmtList, node) + + # As I've painfully found out, the order here really DOES matter. + result.add createFutureVarCompletions(futureVarIdents, node) + if node[0].kind == nnkEmpty: if not subTypeIsVoid: result.add newCall(newIdentNode("complete"), retFutureSym, @@ -158,8 +167,6 @@ proc processBody(node, retFutureSym: NimNode, else: result.add newCall(newIdentNode("complete"), retFutureSym, x) - result.add createFutureVarCompletions(futureVarIdents) - result.add newNimNode(nnkReturnStmt, node).add(newNilLit()) return # Don't process the children of this return stmt of nnkCommand, nnkCall: @@ -347,6 +354,8 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = futureVarIdents, nil) # don't do anything with forward bodies (empty) if procBody.kind != nnkEmpty: + procBody.add(createFutureVarCompletions(futureVarIdents, nil)) + if not subtypeIsVoid: procBody.insert(0, newNimNode(nnkPragma).add(newIdentNode("push"), newNimNode(nnkExprColonExpr).add(newNimNode(nnkBracketExpr).add( @@ -366,8 +375,6 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = # -> complete(retFuture) procBody.add(newCall(newIdentNode("complete"), retFutureSym)) - procBody.add(createFutureVarCompletions(futureVarIdents)) - var closureIterator = newProc(iteratorNameSym, [newIdentNode("FutureBase")], procBody, nnkIteratorDef) closureIterator[4] = newNimNode(nnkPragma, prc[6]).add(newIdentNode("closure")) @@ -377,7 +384,7 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = #var cbName = newIdentNode("cb") var procCb = getAst createCb(retFutureSym, iteratorNameSym, newStrLitNode(prc[0].getName), - createFutureVarCompletions(futureVarIdents)) + createFutureVarCompletions(futureVarIdents, nil)) outerProcBody.add procCb # -> return retFuture @@ -398,7 +405,7 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = if procBody.kind != nnkEmpty: result[6] = outerProcBody #echo(treeRepr(result)) - #if prc[0].getName == "beta": + #if prc[0].getName == "recvLineInto": # echo(toStrLit(result)) macro async*(prc: untyped): untyped = diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index 2d5c65001..1ec751a64 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -464,8 +464,7 @@ proc recvLineInto*(socket: AsyncSocket, resString: FutureVar[string], ## The partial line **will be lost**. ## ## The ``maxLength`` parameter determines the maximum amount of characters - ## that can be read before a ``ValueError`` is raised. This prevents Denial - ## of Service (DOS) attacks. + ## that can be read. ``resString`` will be truncated after that. ## ## **Warning**: The ``Peek`` flag is not yet implemented. ## @@ -519,10 +518,7 @@ proc recvLineInto*(socket: AsyncSocket, resString: FutureVar[string], socket.currPos.inc() # Verify that this isn't a DOS attack: #3847. - if resString.mget.len > maxLength: - let msg = "recvLine received more than the specified `maxLength` " & - "allowed." - raise newException(ValueError, msg) + if resString.mget.len > maxLength: break else: var c = "" while true: @@ -546,10 +542,7 @@ proc recvLineInto*(socket: AsyncSocket, resString: FutureVar[string], resString.mget.add c # Verify that this isn't a DOS attack: #3847. - if resString.mget.len > maxLength: - let msg = "recvLine received more than the specified `maxLength` " & - "allowed." - raise newException(ValueError, msg) + if resString.mget.len > maxLength: break resString.complete() proc recvLine*(socket: AsyncSocket, @@ -569,8 +562,7 @@ proc recvLine*(socket: AsyncSocket, ## The partial line **will be lost**. ## ## The ``maxLength`` parameter determines the maximum amount of characters - ## that can be read before a ``ValueError`` is raised. This prevents Denial - ## of Service (DOS) attacks. + ## that can be read. The result is truncated after that. ## ## **Warning**: The ``Peek`` flag is not yet implemented. ## diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index 8cdb83e19..f438a85e7 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -418,7 +418,7 @@ proc spawn*(call: expr): expr {.magic: "Spawn".} proc pinnedSpawn*(id: ThreadId; call: expr): expr {.magic: "Spawn".} ## always spawns a new task on the worker thread with ``id``, so that ## the 'call' is **always** executed on - ## the this thread. 'call' has to be proc call 'p(...)' where 'p' + ## the thread. 'call' has to be proc call 'p(...)' where 'p' ## is gcsafe and has a return type that is either 'void' or compatible ## with ``FlowVar[T]``. diff --git a/lib/pure/httpcore.nim b/lib/pure/httpcore.nim index aa8f1958d..a5ab40ca4 100644 --- a/lib/pure/httpcore.nim +++ b/lib/pure/httpcore.nim @@ -285,7 +285,7 @@ proc `$`*(code: HttpCode): string = proc `==`*(a, b: HttpCode): bool {.borrow.} proc `==`*(rawCode: string, code: HttpCode): bool = - return rawCode.toLower() == ($code).toLower() + return cmpIgnoreCase(rawCode, $code) == 0 proc is2xx*(code: HttpCode): bool = ## Determines whether ``code`` is a 2xx HTTP status code. @@ -304,7 +304,7 @@ proc is5xx*(code: HttpCode): bool = return code.int in {500 .. 599} proc `$`*(httpMethod: HttpMethod): string = - return (system.`$`(httpMethod))[4 .. ^1].toUpper() + return (system.`$`(httpMethod))[4 .. ^1].toUpperAscii() when isMainModule: var test = newHttpHeaders() diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 7f6783358..56f8b9399 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -1010,8 +1010,7 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1, ## the specified time an ETimeout exception will be raised. ## ## The ``maxLength`` parameter determines the maximum amount of characters - ## that can be read before a ``ValueError`` is raised. This prevents Denial - ## of Service (DOS) attacks. + ## that can be read. The result is truncated after that. ## ## **Warning**: Only the ``SafeDisconn`` flag is currently supported. @@ -1047,10 +1046,7 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1, add(line.string, c) # Verify that this isn't a DOS attack: #3847. - if line.string.len > maxLength: - let msg = "recvLine received more than the specified `maxLength` " & - "allowed." - raise newException(ValueError, msg) + if line.string.len > maxLength: break proc recvLine*(socket: Socket, timeout = -1, flags = {SocketFlag.SafeDisconn}, @@ -1069,8 +1065,7 @@ proc recvLine*(socket: Socket, timeout = -1, ## the specified time an ETimeout exception will be raised. ## ## The ``maxLength`` parameter determines the maximum amount of characters - ## that can be read before a ``ValueError`` is raised. This prevents Denial - ## of Service (DOS) attacks. + ## that can be read. The result is truncated after that. ## ## **Warning**: Only the ``SafeDisconn`` flag is currently supported. result = "" |