Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
307 changes: 170 additions & 137 deletions README.md

Large diffs are not rendered by default.

22 changes: 14 additions & 8 deletions api/dbghelp.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
from __future__ import print_function
# Import print() function for Python 2.7 compatibility

import ctypes
import ctypes.wintypes
import os
Expand Down Expand Up @@ -48,7 +45,7 @@ class CBA_EVENT_DATA(ctypes.Structure):
('object', ctypes.c_void_p)]

data = ctypes.cast(callbackData, ctypes.POINTER(CBA_EVENT_DATA))
message = data[0].desc.replace("\b", "").strip()
message = data[0].desc.decode('utf-8', errors='replace').replace("\b", "").strip()
logger.info("dllEvent {}>({}) {}".format(self._uniqueProcessHandle, data[0].code, message))
return 1
elif actionCode == 0x07:
Expand Down Expand Up @@ -82,7 +79,7 @@ def initialize(self):
self.SymSetOptions(symoptions)

# Initialize the symbol system
success = self.SymInitialize(self._uniqueProcessHandle, ctypes.c_char_p(self._sympath), ctypes.c_bool(False))
success = self.SymInitialize(self._uniqueProcessHandle, ctypes.c_char_p(self._sympath.encode('utf-8')), ctypes.c_bool(False))
if (success == False):
raise ctypes.WinError()

Expand Down Expand Up @@ -179,7 +176,12 @@ def findFile_Binary(self, name, identifier):

fileLocation = ctypes.create_string_buffer(b'\000' * 1024)
flags = self.SSRVOPT_DWORD
result = self.SymFindFileInPath(self._uniqueProcessHandle, self._sympath, name, id1, id2, 0, flags, fileLocation, None, None)
result = self.SymFindFileInPath(
self._uniqueProcessHandle,
self._sympath.encode('utf-8'),
name.encode('utf-8'),
id1, id2, 0, flags,
fileLocation, None, None)
if (not result):
raise ctypes.WinError()

Expand All @@ -194,8 +196,12 @@ def findFile_Pdb(self, name, identifier):

fileLocation = ctypes.create_string_buffer(b'\000' * 1024)
flags = self.SSRVOPT_GUIDPTR
result = self.SymFindFileInPath_pdb(self._uniqueProcessHandle, self._sympath, name, ctypes.byref(id1), id2, 0,
flags, fileLocation, None, None)
result = self.SymFindFileInPath_pdb(
self._uniqueProcessHandle,
self._sympath.encode('utf-8'),
name.encode('utf-8'),
ctypes.byref(id1), id2, 0,
flags, fileLocation, None, None)

# if the search reports unsuccessful, it is possible it still
# succeeded. This appears common with long distance servers with high latency.
Expand Down
2 changes: 1 addition & 1 deletion api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
testrouteHandler = testhandler.TestHandler()
defaultroutehandler = mainhandler.MainHandler(configuration, symbolroutehandler.getStats())

api = falcon.API()
api = falcon.App()
api.add_route('/{file}', defaultroutehandler)
api.add_route('/symbols/{file}/{identifier}/{rawfile}', symbolroutehandler)
api.add_route('/test/{file1}/{file2}/{file3}', testrouteHandler)
19 changes: 10 additions & 9 deletions api/mainhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ def on_get(self, req, resp, file):
elif (file.endswith(".log")):
return self.on_get_logfile(req, resp, file)
except Exception as e:
resp.body = "error: " + str(e)
resp.text = "error: " + str(e)

def on_get_index(self, req, resp):
diskUsage = 0 # sum([getFolderSize(server.get("cacheLocation", None)) for server in self._config.servers()])
diskUsage += getFolderSize(self._config.cacheLocation())
self._template = env.get_template('main.html.jinja')
resp.body = self._template.render(
resp.text = self._template.render(
serverName=self._config.name(),
admin=self._config.administrator(),
clientConfig=self._config.sympath(),
Expand All @@ -69,13 +69,14 @@ def on_get_index(self, req, resp):
diskUsage=diskUsage,
logfiles=self._config.logfiles()
)
resp.content_type = "html"

resp.content_type = "text/html"

def on_get_config(self, req, resp):
configLocation = self._config.configFile()
resp.stream = open(configLocation, 'rb')
resp.stream_len = os.path.getsize(configLocation)
resp.content_type = "json"
resp.content_type = "application/json"

def on_get_statistics(self, req, resp):
# Build a dictionary of information to send
Expand All @@ -85,16 +86,16 @@ def on_get_statistics(self, req, resp):
stats.diskUsage += getFolderSize(self._config.cacheLocation())
stats.numAcceptedRequests = stats.numRequests.value - stats.numExcluded.value

resp.data = JsonEncoder().encode(stats)
resp.content_type = "json"
resp.text = JsonEncoder().encode(stats)
resp.content_type = "application/json"

def on_get_symbols(self, req, resp):
# Build a dictionary of information to send
# Serialise it and send
symbols = self._statistics.getSymbols()

resp.data = JsonEncoder().encode(symbols)
resp.content_type = "json"
resp.text = JsonEncoder().encode(symbols)
resp.content_type = "application/json"

def on_get_logfile(self, req, resp, file):
# Get the list of log files
Expand All @@ -104,4 +105,4 @@ def on_get_logfile(self, req, resp, file):
logLocation = logfiles[logIndex - 1]
resp.stream = open(logLocation, 'rb')
resp.stream_len = os.path.getsize(logLocation)
resp.content_type = "text"
resp.content_type = "text/plain"
6 changes: 1 addition & 5 deletions api/objectpool.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
# Python 3+ has module "queue", while 2.7 has module "Queue"
try:
import queue
except ImportError:
import Queue as queue
import queue

from contextlib import contextmanager
import threading
Expand Down
10 changes: 6 additions & 4 deletions api/requeststatistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,19 @@ def __init__(self, file):
self.serverHits = {}

def recordServerHit(self, server):
counter = self.serverHits.get(server.identifer(), None)
sid = server.identifier()
counter = self.serverHits.get(sid, None)
if counter is None:
counter = AtomicCounter()
self.serverHits[server.identifer()] = counter
self.serverHits[sid] = counter
counter.increment()

def recordServerMiss(self, server):
counter = self.serverMisses.get(server.identifer(), None)
sid = server.identifier()
counter = self.serverMisses.get(sid, None)
if counter is None:
counter = AtomicCounter()
self.serverMisses[server.identifer()] = counter
self.serverMisses[sid] = counter
counter.increment()

def encodeJSON(self):
Expand Down
3 changes: 2 additions & 1 deletion api/symbolhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ def on_get(self, req, resp, file, identifier, rawfile):

except Exception as e:
logging.error("{}".format(str(e)))
resp.body = "404 could not find requested file.\nError: " + str(e)
resp.text = "404 could not find requested file.\nError: " + str(e)
resp.content_type = "text/plain"
resp.status = falcon.HTTP_404

self._statistics.endRequest(statRecord, file, identifier, symbolLocation, cacheHit, excluded, valid,
Expand Down
6 changes: 5 additions & 1 deletion api/symbolserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,9 @@ def findFile(self, file, identifier):
self._previousResults[recordId] = newRecord
return newRecord.location, False, True

def identifer(self):
# Backwards-compatible accessor for the server identifier
def identifier(self):
return self._identifier

# Temporary shim to support older code paths referencing the misspelled name
identifer = identifier
3 changes: 2 additions & 1 deletion api/testhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ def on_get(self, req, resp, file1, file2, file3):
resp.content_type = "application/octet-stream"

except Exception as e:
resp.body = "error: " + str(e)
resp.text = "error: " + str(e)
resp.content_type = "text/plain"
4 changes: 2 additions & 2 deletions config/default.pysymproxy.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "PySymProxy - Default configuration",
"host": "localhost",
"administrator": "!enter your contact details!",
"default_sympath": "srv*c:\\symbols*http://localhost:8080/symbols"
"default_sympath": "srv*%LOCALAPPDATA%\\Temp\\SymbolCache*http://localhost:5001/symbols"
},
"general": {
"enableStatistics": true,
Expand All @@ -20,7 +20,7 @@
{
"name": "Microsoft symbol server",
"identifier": "mss",
"remote": "http://msdl.microsoft.com/download/symbols",
"remote": "https://msdl.microsoft.com/download/symbols",
"cacheLocation": "\\\\build-server\\mssymbols",
"retryTimout": 600,
"maxRequests": 10
Expand Down
2 changes: 1 addition & 1 deletion dbghelp/symsrv.yes
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1
9 changes: 5 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
falcon
requests
waitress
jinja2
falcon
requests
waitress
jinja2
markupsafe
7 changes: 2 additions & 5 deletions server.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
from __future__ import print_function
# Import print() function for Python 2.7 compatibility

from api.main import api
from waitress import serve
import logging

logger = logging.getLogger(__name__)
logger.info("Starting SymProxy Server")
print("Test link: http://localhost:8080/symbols/wntdll.pdb/F999943DF7FB4B8EB6D99F2B047BC3101/wntdll.pdb")
serve(api, host='0.0.0.0', port=8080)
print("Test link: http://localhost:5001/symbols/wntdll.pdb/F999943DF7FB4B8EB6D99F2B047BC3101/wntdll.pdb")
serve(api, host='0.0.0.0', port=5001)

#TODO:
# - Add lazy evaluation of storage space
Expand Down